C#动态对象的创建
C#是静态语言,那C#能不能像python一样动态编程呢???
1.DynamicObject
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
dynamic bDynamic = new BDynamicObject();
bDynamic.Name = "BT";
bDynamic.GetName = new Func<int>(() => { return 0; });
Console.WriteLine(bDynamic.Name);
Console.WriteLine(bDynamic.GetName());
}
class BDynamicObject : DynamicObject
{
Dictionary<string, object> _dynamicData = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_dynamicData.ContainsKey(binder.Name))
{
result = _dynamicData[binder.Name];
return true;
}
else
{
result = "Property Not Found";
return false;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_dynamicData[binder.Name] = value;
return true;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
dynamic method = _dynamicData[binder.Name];
Type t = method.GetType();
MethodInfo m = t.GetProperty("Method").GetValue(method) as MethodInfo;
object target = t.GetProperty("Target").GetValue(method);
result = m.Invoke(target, args);
return true;
}
}
}
在这个示例中,重写了3个方法 TrySetMember()、 TryGetMember()和 TryInvokeMember()。
- TrySetMember方法给对象添加了新方法、 属性或字段。
- TryGetMember方法根据GetMemberBinder对象的Name属性检索对象。
- TryInvokeMember方法触发对应的方法委托,执行对应的方法
2.ExpandoObject
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
dynamic exObj = new ExpandoObject();
exObj.Name = "BT";
exObj.GetName = new Func<int>(() => { return 0; });
Console.WriteLine(exObj.Name);
Console.WriteLine(exObj.GetName());
}
}
ExpandoObject的工作方式类似于上面所说的BDynamicObject,区别是不用重写方法。如果需要控制动态对象中属性的添加和访问,则使该对象派生自DynamicObject是最佳选择,使用DynamicObject可以重写几个方法,准确地控制对象与运行库的交互方式。
3.匿名类型
var关键字,它用于表示隐式类型化的变量。var与 new关键字一起使用时,可以创建匿名类型。匿名类型只是一个继承自Object且没有名称的类。该类的定义从初始化器中推断,类似于隐式类型化的变量。
using System;
class Program
{
static void Main(string[] args)
{
var dyanObj = new
{
Name = "BT",
GetName = new Func<int>(() => { return 0; })
};
Console.WriteLine(dyanObj.Name);
Console.WriteLine(dyanObj.GetName());
}
}
这些新对象的类型名未知。 编译器为类型伪造 了一个名称,但只有编译器才能使用它。我们不能也不应使用新对象上的任何类型反射 ,因为这不会得到一致的结果。