使用动态方法添加方法?

11

我正在尝试在运行时添加函数,类似于这样:

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' does not contain a definition for 'Quack'

使用者的查询中,Duck并没有定义Quack

动态类型(dynamic)不应该允许我这样做吗?

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

我已经有了我的Duck类,怎么让它变成Expando呢?- 我能让鸭子(Duck)表现得像Expando吗?


由于某些非常模糊的原因,我的帖子被删除了。顺便说一下,您不能从ExpandoObject派生,并且如果您想让您的对象像那个对象一样运行,我认为您有两个解决方案:1.创建Expando并最初添加所有属性和方法您在Duck中拥有,并且不使用Duck。2.生成自己的ExpandoObject。请参阅此处:Dynamic Behaviour on Objects at Runtime With Custom ExpandoObject以获取更详细的示例并从中派生Duck。 - Tigran
1个回答

18

你无法向一个已存在的类型添加任何类型的属性(包括函数)。

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继承。像这样(改编自此 msdn 页面):
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"));

谢谢,但是我为什么要继承自System.Dynamic.DynamicObject呢?我唯一能想到的情况就是覆盖tryGetXXX等方法... - Royi Namir
如果您不想将您的类用作“字典”,例如,如果它表示一个XML或CSV文件,在其中可以动态访问列和元素,如file.nameOfSecondColumn[row] - phipsgabler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接