您的位置:首页 > 编程语言 > C#

C#中的动态类型

2017-08-25 00:00 113 查看
最近研究了一下C#中模拟动态语言的方法,发现可以通过继承DynamicObject来实现。DynamicObject包含的方法可查看msdn或直接查看api,简单说来,DynamicObject提供了一个机制,使得c#可以在运行时处理属性/方法/下标/运算符等操作,并人为定义/修改这些操作的含义。下面给出一个例子来说明。

public class DynObj : DynamicObject
{
Dictionary<string, object> Properties = new Dictionary<string, object>();
Dictionary<string, object[]> Parameters = new Dictionary<string, object[]>();  // 仅用于记录参数便于回溯
Dictionary<string, dynamic> Methods = new Dictionary<string, dynamic>();

// 当找不到函数名称时,进入此方法
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
if (!Parameters.Keys.Contains(binder.Name))
{
Parameters.Add(binder.Name, null);
}

if (args != null)
{
Parameters[binder.Name] = args;
}

if (Methods.ContainsKey(binder.Name))
{
result = Methods[binder.Name](args);
}
else
{
result = null;
}
return true;
}

// 设置动态属性的值,因为方法和属性的设置方法可能一样,所以动态方法也可在此设置
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (!Methods.ContainsKey(binder.Name) && value is Delegate)
{
Methods.Add(binder.Name, value);
}
else if (!Properties.Keys.Contains(binder.Name))
{
Properties.Add(binder.Name, value);
}

return true;
}

// 获取动态属性的值
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return Properties.TryGetValue(binder.Name, out result);
}

// 如果方法已经存在,则不进入TryInvokeMember,直接进入已有方法
public string Test()
{
return "This is a test function";
}
}


上面的类可以通过如下语句调用

dynamic test = new DynObj();
test.a = "hello";
test.b = 10;
test.func1 = new Func<object[], double>((x) => { return Convert.ToInt32(x[0]) + Convert.ToInt32(x[1]); });

Console.WriteLine(test.a);  // 结果为"hello"
Console.WriteLine(test.b);  // 结果为10
Console.WriteLine(test.func1(5, 10));   // 结果为15
Console.WriteLine(test.Test());       // 结果为"This is a test function"
Console.WriteLine(test.Test("Hello"));  // 因为从未定义过,进入TryInvokeMember,但找不到,结果为空


类似地,还可以定义下标和运算符的动态处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态类