文档章节

C#中的动态类型

propagator
 propagator
发布于 2017/08/25 11:51
字数 420
阅读 13
收藏 0

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

 

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

© 著作权归作者所有

共有 人打赏支持
propagator
粉丝 6
博文 26
码字总数 28868
作品 0
昆明
语言设计中的鸭子类型风格

在动态语言的世界里一直流传着一种叫做鸭子类型的风格,其来自谚语:“如果行鸭子一样走路,像鸭子一样呱呱叫,那它就是一只鸭子”。 从鸭子类型,我们可以联想到它的推导,并不在乎类型的真...

justjavac
2013/07/04
269
0
如何快速编写和调试 Emit 生成 IL 的代码

.NET Core/.NET Framework 的 命名空间为我们提供了动态生成 IL 代码的能力。利用这项能力,我们能够在运行时生成一段代码/一个方法/一个类/一个程序集。 大家都知道反射的性能很差,通过缓存...

wpwalter
04/27
0
0
Visual C# .NET 2003 语言的改变

Visual C# .NET 2003 语言的改变 Prashant Sridharan Microsoft Corporation 2002年12月30日 适用于: Microsoft Visual Studio® C# 2003 摘要:为了与欧洲计算机制造商协会 (ECMA) 的 C# 规...

晨曦之光
2012/03/09
42
0
从数据到代码——通过代码生成机制实现强类型编程[上篇]

我不知道大家对CodeDOM的代码生成机制是否熟悉,但是有一点可以确定:如果你使用过Visual Studio,你就应该体验过它带给我们在编程上的便利。随便列举三种典型的代码生成的场景:在创建强类型...

长平狐
2012/09/04
47
0
像javascript 一样写c# 。

摘要: .Net 4 中引入了 dynamic 动态类型,着实让我们兴奋的一把,不过相对其它动态语言, 还是有不少差距的。不过借助 CodePlex 上的一个开源项目 Clay,我们可以写出以下不可思议的代码:v...

BryanYang
2013/09/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java并发备忘

不安全的“先检查后执行”,代码形式如下: if(条件满足){ //这里容易出现线程安全问题//doSomething}else{//doOther} 读取-修改-写入 原子操作:使用CAS技术,即首先从V中读取...

Funcy1122
今天
0
0
SpringBoot2.0 停机

最近新建了个SpringBoot2.0的项目,因为原来一直使用的是传统的Tomcat部署war包的形式,所以这次SpringBoot内置Tomcat部署jar包的时候遇到了很多问题。其中一个就是因为没有外置的Tomcat容器...

Canaan_
昨天
0
1
Confluence 6 外部参考

一个外部参考的意思是任何站点链接到你 Confluence 的实例。任何时候当 Confluence 的用户单击这个外部链接的时候,Confluence 可以记录这次单击为参考。 在默认的情况下,外部链接的参考链接...

honeymose
昨天
0
0
Android中的设计模式之抽象工厂模式

参考 《设计模式解析》 第十一章 Abstract Factory模式 《设计模式:可复用面向对象软件的基础 》3.1 Abstract Factory 抽象工厂 对象创建型模式 《Android源码设计模式解析与实战》第6章 创...

newtrek
昨天
0
0
Redis | 地理空间(GEO)的一个坑

Redis的地理空间(Geo)是个好东西,轻轻松松的就可以把地图描点的问题处理了, 最近却遇到一个坑...Redis采用的Msater-Slave模式, 运用GEORADIUS在salve读取对应的数据,新增了从节点但是从不返...

云迹
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部