C#:从泛型调用外部程序集中的重载方法

C#: Call overloaded method in external assembly from generic

我有一个引用包含多个重载实例方法的第 3 方 c# 程序集的项目。我想在我的代码中通过泛型调用这些方法之一,调用参数类型与泛型类型匹配的实例方法:

void GetVal<T>(ref T val)
{
    VendorLib v = new VendorLib();
    v.GetVal(ref val); 
}

// error CS1503: Argument 1: cannot convert from 'ref T' to 'ref bool'

我最接近的是通过使用动态变量,但这会导致运行时异常,因为参数 d 解析为 bool,即使泛型的类型是 ulong,从而绑定了不正确的方法:

class MyClass
{
    void Caller()
    {
        ulong val = 0;
        this.GetValue<ulong>(ref val);
    }

    void GetValue<T>(ref T val)
    {
        dynamic d = val; 
        GetValDynamic(ref d);
    }

    void GetValDynamic(ref dynamic val)
    {
        VendorLib v = new VendorLib();
        v.GetVal(ref val);
    }
}

异常: 结果消息:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:'VendorLib.GetVal(ref bool)' 的最佳重载方法匹配有一些无效参数

供应商库包含多个 GetVal 重载,其中 GetVal(ref bool) 是一个,GetVal(ref ulong) 是另一个。

为什么没有绑定正确的方法?

谢谢!

valdynamic,而不是 boolulong。这是错误的类型。通过使用 dynamic,您只是在欺骗自己,让自己脱离编译时检查,而只是在运行时遇到错误。

查看此代码的工作方式,泛型和动态的唯一目的是找到一种将 bool 或 ulong 传递给 GetVal(...) 的方法。从您的代码看来,唯一可能需要 public 的方法是 Caller(),在这种情况下,您可以将所有这些隐藏在一个公共接口后面。

class MyClassULong : IMyClass
{
    void Caller()
    {
        ulong val = 0;
        this.GetValue(ref val);
    }

    void GetValue(ulong val)
    {
        VendorLib v = new VendorLib();
        v.GetVal(ref val);
    }

}

class MyClassBool : IMyClass
{
    void Caller()
    {
        bool val = false;
        this.GetValue(ref val);
    }

    void GetValue(bool val)
    {
        VendorLib v = new VendorLib();
        v.GetVal(ref val);
    }

}

public interface IMyClass
{
    void Caller();
}

然后任何调用 Caller() 的代码都将针对 IMyClass 编写,因此不会关心您使用的是哪个实现。

public void CallIt(IMyClass myClass)
{
    myClass.Caller();
}

有很多模式可以解决这类问题。为了更好地理解,您确实需要花大量时间阅读 C# 中的 OOP,并花时间编码。

如果您不想检查 typeof(T) 并手动调用相应的方法,那么反射可以工作。像这样...

  public class MyVendorLibWrapper
  {
    private readonly VendorLib vendorLib;

    public MyVendorLibWrapper()
    {
      this.vendorLib = new VendorLib();
    }

    public T GetValue<T>()
    {
      MethodInfo method = typeof(VendorLib)
        .GetMethod("GetVal", new Type[] { typeof(T).MakeByRefType() });

      object[] arguments = new object[] { default(T) };
      method.Invoke(this.vendorLib, arguments);
      return (T)arguments[0];
    }
  }

并这样称呼...

MyVendorLibWrapper wrapper = new MyVendorLibWrapper();
int x = wrapper.GetValue<int>();