下面是详细的攻略:
C#Dynamic之:ExpandoObject,DynamicObject,DynamicMetaObject的应用(下)
一、ExpandoObject
ExpandoObject是一个动态类型,它允许我们在运行时添加或删除属性,甚至可以动态更改属性的类型。ExpandoObject非常方便,可以用来处理一些未知的数据结构。
1. 添加属性
我们可以使用ExpandoObject来动态地添加属性。例如,我们可以利用它来创建一个JavaScript风格的字典。
dynamic dynamicObj = new ExpandoObject();
dynamicObj.first = "John";
dynamicObj.last = "Doe";
dynamicObj.address = new ExpandoObject();
dynamicObj.address.street = "123 Main St";
dynamicObj.address.city = "Seattle";
dynamicObj.address.zip = "98101";
在上面的示例中,我们创建了一个dynamic类型的对象dynamicObj,然后动态地添加了first、last、address三个属性。其中,address属性又是一个ExpandoObject类型的对象,我们又动态地为它添加了street、city和zip三个属性。
2. 获取属性
我们可以像访问普通对象一样,通过.操作符来访问ExpandoObject上的属性。
Console.WriteLine(dynamicObj.first); // John
Console.WriteLine(dynamicObj.last); // Doe
Console.WriteLine(dynamicObj.address.street); // 123 Main St
Console.WriteLine(dynamicObj.address.city); // Seattle
Console.WriteLine(dynamicObj.address.zip); // 98101
3. 删除属性
我们也可以使用ExpandoObject来动态地删除属性。
((IDictionary<string, object>)dynamicObj).Remove("address");
在上面的示例中,我们将address属性从dynamicObj中删除了。
二、DynamicObject
DynamicObject是一个抽象类,它提供了一些方法来让我们自定义动态对象的行为。我们可以继承DynamicObject类来创建自己的动态类型,并重写它提供的方法来实现所需的行为。
1. 重写TryGetMember方法
我们可以通过重写DynamicObject类的TryGetMember方法来提供对动态对象的成员的访问行为。
public class DynamicDictionary : DynamicObject
{
private 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 void Add(string key, object value)
{
_dictionary[key.ToLower()] = value;
}
// other methods omitted for brevity
}
在上面的示例中,我们创建了一个DynamicDictionary类,继承自DynamicObject,它包含了一个Dictionary
使用示例:
dynamic dict = new DynamicDictionary();
dict.Name = "John";
dict.Age = 20;
Console.WriteLine(dict.Name); // John
Console.WriteLine(dict.Age); // 20
在上面的示例中,我们创建了一个dynamic类型的对象dict,它是DynamicDictionary的实例。然后我们动态地为dict添加了两个属性Name和Age。接着,我们通过dict.Name和dict.Age来访问这两个属性,它们的值分别是"John"和20。
2. 重写TryInvokeMember方法
我们还可以通过重写DynamicObject类的TryInvokeMember方法来提供对动态对象的方法调用行为。
public class DynamicCalculator : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var arg1 = (double)args[0];
var arg2 = (double)args[1];
switch (binder.Name.ToLower())
{
case "add":
result = arg1 + arg2;
return true;
case "subtract":
result = arg1 - arg2;
return true;
case "multiply":
result = arg1 * arg2;
return true;
case "divide":
result = arg1 / arg2;
return true;
default:
result = null;
return false;
}
}
}
在上面的示例中,我们创建了一个DynamicCalculator类,它继承自DynamicObject。我们重写了TryInvokeMember方法,当我们调用DynamicCalculator的一个方法时,它会根据方法名动态执行相应的操作。例如,当我们调用Add(2,3)时,它会返回5,因为2+3=5。
使用示例:
dynamic calc = new DynamicCalculator();
Console.WriteLine(calc.Add(2, 3)); // 5
Console.WriteLine(calc.Subtract(5, 2)); // 3
Console.WriteLine(calc.Multiply(3, 4)); // 12
Console.WriteLine(calc.Divide(10, 2)); // 5
在上面的示例中,我们创建了一个dynamic类型的对象calc,它是DynamicCalculator的实例。然后我们动态地调用了它的四个方法Add、Subtract、Multiply和Divide,它们的返回值分别是5、3、12和5。
三、DynamicMetaObject
DynamicMetaObject是DynamicObject的一个扩展类,它提供了一些方法来让我们更加灵活地定义动态对象的行为。我们可以继承DynamicMetaObject类来创建自己的动态类型,并重写它提供的方法来实现所需的行为。
1. 重写GetDynamicMemberNames方法
我们可以通过重写DynamicMetaObject类的GetDynamicMemberNames方法来动态地返回动态对象的所有属性。
public class DynamicDictionary : DynamicObject
{
private Dictionary<string, object> _dictionary = new Dictionary<string, object>();
public override IEnumerable<string> GetDynamicMemberNames()
{
return _dictionary.Keys;
}
// other methods omitted for brevity
}
在上面的示例中,我们重写了GetDynamicMemberNames方法,它会返回_dynamicDictionary的所有属性名。这使得我们可以使用foreach循环来遍历_dynamicDictionary的所有属性。
使用示例:
dynamic dict = new DynamicDictionary();
dict.Name = "John";
dict.Age = 20;
foreach (var prop in dict)
{
Console.WriteLine("{0} = {1}", prop, dict[prop]);
}
在上面的示例中,我们创建了一个dynamic类型的对象dict,它是DynamicDictionary的实例。然后我们动态地为dict添加了两个属性Name和Age。接着,我们使用foreach循环遍历dict的所有属性,并输出它们的名称和值。
2. 重写TryConvert方法
我们还可以通过重写DynamicMetaObject类的TryConvert方法来提供类型转换的行为。例如,当我们将一个动态对象转换为某个具体的类型时,它会调用我们重写的TryConvert方法,来决定如何将动态对象转换为目标类型。
public class DynamicPerson : DynamicObject
{
private string _name;
private int _age;
public DynamicPerson(string name, int age)
{
_name = name;
_age = age;
}
public override bool TryConvert(ConvertBinder binder, out object result)
{
if (binder.Type == typeof(string))
{
result = string.Format("{0} ({1})", _name, _age);
return true;
}
else if (binder.Type == typeof(int))
{
result = _age;
return true;
}
else
{
result = null;
return false;
}
}
}
在上面的示例中,我们创建了一个DynamicPerson类,它继承自DynamicObject。我们重写了TryConvert方法,当我们将DynamicPerson对象转换为字符串或整数时,它会返回相应的结果。
使用示例:
dynamic person = new DynamicPerson("John Doe", 20);
string strNameAge = (string)person;
int intAge = (int)person;
Console.WriteLine(strNameAge); // John Doe (20)
Console.WriteLine(intAge); // 20
在上面的示例中,我们创建了一个dynamic类型的对象person,它是DynamicPerson的实例。然后,我们将person分别转换为字符串和整数,它们分别是"John Doe (20)"和20。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下) - Python技术站