C#中的动态类型

本文介绍了一种在C#中模拟动态语言特性的方法,通过继承DynamicObject并重写其部分方法来实现动态属性和方法的处理。文章提供了具体代码示例,展示了如何自定义动态属性和方法的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

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

转载于:https://my.oschina.net/propagator/blog/1523404

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值