【问题标题】:Dynamic Action<T> : Invalid Arguments when executedDynamic Action<T> : 执行时参数无效
【发布时间】:2015-12-07 08:19:48
【问题描述】:

在我的大型项目中有很多地方需要切换类型。显然我不能在 .NET 中做到这一点(以一种足够简单的方式让我满意),所以我必须进行大量的转换。这段代码是试图在概念验证中隐藏其中一些内容的结果。

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

public class Base { }
public class Derived : Base { public string Name { get; set; } }

和我的班级:

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);
    }
}

我运行它:

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);
}    

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

附加信息:Delegate 'System.Action' 有一些无效参数

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

【问题讨论】:

    标签: c# generics dynamic types


    【解决方案1】:

    您的item 参数不是dynamic。因为它的静态类型为T,所以类型T(恰好是Base)将用于重载解析。 Action&lt;Derived&gt; 不能用 Base 参数调用。

    要在此处使用dynamic,您还需要将item dynamic:将action(item); 更改为action((dynamic) item);

    【讨论】:

      【解决方案2】:

      尝试另一个级别的 lambda。除了工作之外,我预计这将比使用 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);
          }
      }
      

      【讨论】:

      • 哇,我从来没有尝试过。非常感谢!
      • 知道如何删除Action&lt;K&gt; 吗?
      猜你喜欢
      • 2015-11-10
      • 2011-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多