介绍
DynamicObject类使开发人员能够实现动态类型或在运行时动态行为。开发人员无法直接创建此类的实例。相反,他需要扩展类以使其具有所需的行为。例如,对于具有动态行为的类,请参见下面的最小步骤,以创建和使用属性和方法。
dynamic d; // defines field d as dynamic and the type of the d determines at runtime
d = 10; // at runtime, type of the d resolved as Int.32
步骤1:扩展DynamicObject类
创建一个类并使用DynamicObject进行扩展。
class Employee : DynamicObject // create a class and extend with DynamicObject
{
private IDictionary _members = new Dictionary();
}
步骤2:定义字典
定义一个字典来存储动态对象,例如方法,属性及其值。
class Employee : DynamicObject // create a class and extend with DynamicObject
{
private IDictionary _members = new Dictionary
{ Console.WriteLine("Method is Invoked"); }); // Create a method GetSalary at runtime
Console.ReadKey();
}
}
TrySetMember参数
- Binder 提供有关正在尝试设置值的对象的信息。binder.Name属性提供成员的名称。
- Result 是要为动态对象设置的值。
- Returns true如果操作成功;否则为false
TryGetMember提供实现以获取属性的值。例如,var当我们尝试访问时employee.Id,DLR使用语言绑定程序查找静态定义。如果没有属性,则DLR调用TryGetMember。
class Employee: DynamicObject // create a class and extend with DynamicObject
{
private IDictionary _members = new Dictionary();
public override bool TrySetMember(SetMemberBinder binder, object value) {...}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return _members.TryGetValue(binder.Name, out result);
}
}
class Program
{
static void Main(string[] args)
{
dynamic employee = new Employee();
employee.Id = 1007; // create a property Id and assign value 1007 at runtime
employee.Name = "Bhupathi"; // create a property Name and
// assign value "Bhupathi" at runtime
employee.GetSalary = (Action)(() =>
{ Console.WriteLine("Method is Invoked"); }); // Create a method
// GetSalary at runtime
Console.WriteLine("List of values in employee object");
Console.WriteLine($"Employee Id :
{employee.Id}"); // retrieves the value of property id in employee object
Console.WriteLine($"Employee Name : {employee.Name}"); // retrieves the value
// of property Name in
// employee object
Console.ReadKey();
}
}
在我们的示例行int eid = employee.Id中,TryGetMember返回Id的值。
TryGetMember参数
- Binder提供有关试图检索该值的对象的信息。binder.Name属性提供成员的名称。
- Result 是尝试检索值的动态对象的返回值。
- Returns true如果操作成功;否则为false。
TryInvokeMember 提供调用方法的实现。
class Employee: DynamicObject // create a class and extend with DynamicObject
{
private IDictionary _members = new Dictionary();
public override bool TrySetMember(SetMemberBinder binder, object value) {...}
public override bool TryGetMember(GetMemberBinder binder, out object result) {...}
public override bool TryInvokeMember
(InvokeMemberBinder binder, object[] args, out object result)
{
Type dictType = typeof(Dictionary);
try
{
result = dictType.InvokeMember(
binder.Name,
BindingFlags.InvokeMethod,
null, _members, args);
return true;
}
catch
{
return false;
}
}
}
class Program
{
static void Main(string[] args)
{
dynamic employee = new Employee();
employee.GetSalary = (Action)(() =>
{ Console.WriteLine("Method is Invoked"); }); // Create a method
// GetSalary at runtime
employee.GetSalary();
Console.ReadKey();
}
}
在我们的示例中,employee.GetSalary(); GetSalary方法将与null参数一起调用。
TryInvokeMember参数
- Binder提供有关正在尝试调用的对象或方法的信息。binder.Name属性提供成员的名称。
- Args[] 与方法一起传递的参数
- Result 执行后从方法返回的值
- Returns true如果操作成功;否则为false
ExpandoObject是IDynamicMetaObjectProvider的全部功能的类和实现,其也是.NET的动态库的一部分。当您不需要动态类的任何自定义行为时,ExpandoObject非常有用。
结论动态对象在运行时发出代码,并且非常昂贵。除非需要,否则不要使用动态对象,例如使用COM API(例如Office API)。