那我开始讲解C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaObject的应用(上)的完整攻略。
1. 概述
首先,需要了解什么是动态类型,以及为什么需要使用动态类型。在C#中,变量的类型实际上是由编译器推断出来的,也就是静态类型。而动态类型是指在运行时才确定类型的类型。动态类型的主要作用是在不确定类型时,可以通过运行时信息来确定类型,从而实现更灵活的编程。
在C#中,提供了一些机制来支持动态类型,其中ExpandoObject、DynamicObject和DynamicMetaObject是比较常见的。
2. ExpandoObject
ExpandoObject是一种可以动态添加属性和方法的对象。通过ExpandoObject,可以在运行时动态添加属性和方法,而不需要在编译时就确定属性和方法。下面是一个使用ExpandoObject的示例:
dynamic person = new ExpandoObject();
person.Name = "John";
person.Age = 30;
person.SayHello = (Action)(() => Console.WriteLine("Hello, my name is " + person.Name));
person.SayHello();
在上面的示例中,我们创建了一个ExpandoObject对象,并且动态的添加了Name、Age属性和SayHello方法。通过这种方式,我们可以灵活的定义对象的属性和方法,并在运行时动态的添加和使用它们。
3. DynamicObject
DynamicObject是一个可以重写成员访问的类。通过继承DynamicObject,可以动态定义对象的成员访问行为。下面是一个使用DynamicObject的示例:
class MyDynamicClass : DynamicObject
{
private readonly Dictionary<string, object> _dictionary =
new Dictionary<string, object>();
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 obj = new MyDynamicClass();
obj.Name = "John";
Console.WriteLine(obj.Name);
在上面的示例中,我们自定义了一个MyDynamicClass类,该类继承自DynamicObject并重载了TryGetMember和TrySetMember方法。在TryGetMember和TrySetMember方法中,我们实现了访问对象成员的方式,例如可以将对象的属性名称转化为小写后在Dictionary中查找对应的值。
4. DynamicMetaObject
DynamicMetaObject是一个提供动态行为元数据的类。通过重载DynamicMetaObject,可以实现更高级的动态类型行为。下面是一个使用DynamicMetaObject的示例:
class MyDynamicClass : DynamicObject
{
private readonly Dictionary<string, object> _dictionary =
new Dictionary<string, object>();
public override DynamicMetaObject GetMetaObject(Expression parameter)
{
return new MyDynamicMetaObject(parameter, this);
}
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;
}
}
class MyDynamicMetaObject : DynamicMetaObject
{
public MyDynamicMetaObject(Expression expression, object value)
: base(expression, BindingRestrictions.Empty, value)
{
}
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
var name = Expression.Constant(binder.Name.ToLower());
var dictionary = Expression.Property(Expression.Constant(Value), "Dictionary");
var index = Expression.Call(dictionary, "TryGetValue", null, name,
Expression.Variable(typeof(object)));
var restriction = BindingRestrictions.GetTypeRestriction(Expression, LimitType);
var value = Expression.Variable(typeof(object));
var fallback = Expression.Block(
Expression.Assign(value, Expression.Default(typeof(object))),
Expression.Convert(value, binder.ReturnType));
var binding = new DynamicMetaObject(
Expression.Block(
new[] { value },
Expression.Condition(index, Expression.Convert(Expression.Property(
Expression.Variable(value),
"Value"),
binder.ReturnType),
fallback)),
restriction,
this);
return binding;
}
}
dynamic obj = new MyDynamicClass();
obj.Name = "John";
Console.WriteLine(obj.Name);
在上面的示例中,我们自定义了一个MyDynamicClass类,该类继承自DynamicObject并重载了GetMetaObject、TryGetMember和TrySetMember方法。在GetMetaObject方法中,我们返回了一个MyDynamicMetaObject实例,该实例提供了我们需要实现的动态行为元数据。
在MyDynamicMetaObject类中,我们重载了BindGetMember方法,该方法定义了用于动态访问成员的逻辑。这里我们使用Expression来实现了一个动态的条件语句,该条件语句尝试从Dictionary中读取属性值,如果成功则返回对应的值,否则返回默认值。
5. 总结
以上就是对于C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaObject的应用(上)的完整攻略。ExpandoObject、DynamicObject和DynamicMetaObject都是C#中实现动态类型的重要机制,使用它们可以带来更灵活的编程体验,使编程更加便捷。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(上) - Python技术站