动态操作<T>:执行时无效的参数

Jon*_*lis 4 c# generics types dynamic

我在规模很大的项目中有很多地方需要打开一个类型.显然我不能在.NET中做到这一点(以一种简单到足以满足我的方式),所以我必须进行相当数量的转换.此代码是试图在概念证明中隐藏其中一些内容的结果.

我有一个简单的继承模型:

public class Base { }
public class Derived : Base { public string Name { get; set; } }
Run Code Online (Sandbox Code Playgroud)

和我的班级:

public sealed class TypeSwitch<T> 
{
    private Dictionary<Type, dynamic> _dict;

    public TypeSwitch()
    {
        _dict = new Dictionary<Type, dynamic>();
    }

    public TypeSwitch<T> Add<K>(Action<K> action) where K : T
    {
        _dict.Add(typeof(K), action);
        return this;
    } 

    public void Execute(T item)
    {
        var type = item.GetType();
        var action = _dict[type];

        action(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

我运行它:

static void Main(string[] args)
{
    var ts = new TypeSwitch<Base>();
    ts.Add<Derived>(d => { Console.WriteLine(d.Name); });

    Base b = new Derived { Name = "Jonesopolis" };
    ts.Execute(b);
}    
Run Code Online (Sandbox Code Playgroud)

当我到达时,action(item)我得到一个RuntimeBinderException说法

附加信息:委托'System.Action <ConsoleApp.Derived>'有一些无效的参数

如果我可以使它工作,这将是非常光滑和有用的.有人可以向我解释我错过了什么吗?有可能让这个工作吗?

小智 6

你的item参数不是dynamic.因为它是静态类型的T,所以该类型T(恰好是Base)将用于重载解析.Action<Derived>不能用Base参数调用.

dynamic在这里使用,你也需要做item dynamic:action(item);改为action((dynamic) item);.


Mic*_*ter 5

尝试另一个级别的lambdas.除了工作之外,我预计这会比使用快得多dynamic,即使有两个委托被调用.

public sealed class TypeSwitch<T>
{
    private Dictionary<Type, Action<T>> _dict; // no longer dynamic

    public TypeSwitch()
    {
        _dict = new Dictionary<Type, Action<T>>();  // no longer dynamic
    }

    public TypeSwitch<T> Add<K>(Action<K> action) where K : T
    {
        _dict.Add(typeof (K), o => action((K) o)); // outer lambda casts the value before calling the inner lambda
        return this;
    }

    public void Execute(T item)
    {
        var type = item.GetType();
        var action = _dict[type];
        action(item);
    }
}
Run Code Online (Sandbox Code Playgroud)