C#中的动态类型
C#中的动态类型
propagator 发表于4个月前
C#中的动态类型
  • 发表于 4个月前
  • 阅读 8
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

最近研究了一下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,但找不到,结果为空

 

类似地,还可以定义下标和运算符的动态处理。

标签: 动态类
共有 人打赏支持
粉丝 7
博文 21
码字总数 23699
×
propagator
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: