我试图在运行时添加函数,类似于:
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? - 我可以像鸭子一样做鸭子吗?
答案 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());
,如果Duck
和Goose
都有方法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"));