使用Dynamic添加方法?

时间:2012-05-09 09:04:17

标签: c# .net dynamic .net-4.0 dynamic-language-runtime

我试图在运行时添加函数,类似于:

static void Main()
{
 dynamic d = new Duck();
 d.Quack =(Action) (() => Console.WriteLine("1")); //decalre a new method on runtime ??
 d.Quack(); 

}

public class Duck : System.Dynamic.DynamicObject
{
   //...
}

'UserQuery.Duck'不包含'Quack'的定义

Isnt动态应该允许我这样做吗?

全新的ExpandoObject是唯一的解决方案吗?

我的鸭子课程已经。我该如何制作Expando? - 我可以像鸭子一样做鸭子吗?

1 个答案:

答案 0 :(得分:15)

您无法将任何类型(甚至函数)的属性添加到现有类型。

dynamic d = new Duck();
d.Quack = "Quack";//fails because there is no such property on duck

您可以使用ExpandoObject

dynamic d = new ExpandoObject();
d.Quack = (Action)(() => System.Console.WriteLine("1"));
d.Quack(); 

不要与动态类型的内容相混淆。

void speak(dynamic d)
{
 d.Quack();//this is NOT checked at compile time
}

现在我可以:speak(new Duck());speak(new Goose());,如果DuckGoose都有方法Quack(),它会编译并运行不,它引发了一个例外。 (你得到的那个)

当你在dynamic类型上调用方法/属性时,它只在运行时解析它并且不进行编译器检查。

ExpandoObject允许您动态创建属性。


要回答关于评论的问题,我看到的方式是,如果您需要自己的类,需要能够创建新属性,您可以从DynamicObject继承。像这样(改编自this msdn page):

class DynamicDuck : DynamicObject 
{
      Dictionary<string, object> dictionary
           = new Dictionary<string, object>();
    public int Count
    {
        get
        {
           return dictionary.Count;
        }
     }
    public override bool TryGetMember(
          GetMemberBinder binder, out object result)
    {
          string name = binder.Name.ToLower();
            return dictionary.TryGetValue(name, out result);
    }
    public override bool TrySetMember(
         SetMemberBinder binder, object value)
    {
          dictionary[binder.Name.ToLower()] = value;
          return true;
    }
 }

然后你可以这样做:

dynamic d = new DynamicDuck();
d.firstname = "Gideon";
d.Quack = (Action)(() => System.Console.WriteLine("Quack"));