文档章节

C#中的动态类型

propagator
 propagator
发布于 2017/08/25 11:51
字数 420
阅读 11
收藏 0
点赞 0
评论 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
博文 21
码字总数 23862
作品 0
昆明
语言设计中的鸭子类型风格

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

justjavac ⋅ 2013/07/04 ⋅ 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 ⋅ 0

如何快速编写和调试 Emit 生成 IL 的代码

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

wpwalter ⋅ 04/27 ⋅ 0

从数据到代码——通过代码生成机制实现强类型编程[上篇]

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

长平狐 ⋅ 2012/09/04 ⋅ 0

从数据到代码——基于T4的代码生成方式

在之前写一篇文章《从数据到代码》(上篇、下篇)中,我通过基于CodeDOM+Custom Tool的代码生成方式实现了将一个XML表示的消息列表转换成了相应的C#代码,从而达到了强类型编程的目的。实际上...

长平狐 ⋅ 2012/09/04 ⋅ 0

为什么要创建Fantom语言[翻译]

标题:WhyFantom作者:Brian Frank创建世界:6 Dec 07版权:Copyright (c) 2007, Brian Frank and Andy Frank许可:Licensed under the Academic Free License version 3.0 概述 我们真的需要另外......

chunquedong ⋅ 2015/09/10 ⋅ 0

像javascript 一样写c# 。

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

BryanYang ⋅ 2013/09/25 ⋅ 0

基于Visual Studio2010与C#4.0新功能和展望--“dynamic”和“object”之间的关键区别

让我们首先来看看object关键字。我不打算在这方面讲很多,因为它已经自从C#1.0开始只不过是为System.Object准备的一个关键字,这是C#快捷型的层次结构。 (然而,正如埃里克利珀特指出,在...

junwong ⋅ 2012/03/09 ⋅ 0

C#进阶系列——动态Lamada(二:优化)

原文:C#进阶系列——动态Lamada(二:优化) 前言:前几天写了一篇动态Lamada的文章C#进阶系列——动态Lamada,受园友xiao99的启发,今天打算来重新优化下这个动态Lamada的工具类。在此做个笔...

杰克.陈 ⋅ 2017/12/19 ⋅ 0

新JVM语言比较:Ceylon vs Kotlin vs Fantom

现存的计算机编程语言有好几千种,JVM上的语言也有十几种,所以大可不必为没听说过的编程语言感到惊奇。 Java的缺陷 由于工作的原因,对Java比较了解。从Java中我们总结的教训: 对象可以赋值...

chunquedong ⋅ 2015/09/07 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java NIO之字符集

1 字符集和编解码的概念 首先,解释一下什么是字符集。顾名思义,就是字符的集合。它的初衷是把现实世界的符号映射为计算机可以理解的字节。比如我创造一个字符集,叫做sex字符集,就包含两个...

士别三日 ⋅ 27分钟前 ⋅ 0

Spring Bean基础

1、Bean之间引用 <!--如果Bean配置在同一个XML文件中,使用local引用--><ref bean="someBean"/><!--如果Bean配置在不同的XML文件中,使用ref引用--><ref local="someBean"/> 其实两种......

霍淇滨 ⋅ 33分钟前 ⋅ 0

05、基于Consul+Upsync+Nginx实现动态负载均衡

1、Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/local/srcwget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip 解压consu......

北岩 ⋅ 36分钟前 ⋅ 0

Webpack 4 api 了解与使用

webpack 最近升级到了 v4.5+版 01 官方不再支持 node4 以下版本 官方不再支持 node4 以下版本官方不再支持 node4 以下的版本,所以如果你的node版本太低,先开始升级node吧!话说node10 ...

NDweb ⋅ 45分钟前 ⋅ 0

使用nodeJs安装Vue-cli

Vue脚手架就是一个Vue框架开发环境 脚手架的意思是帮你快速开始一个vue的项目,也就是给你一套vue的结构,包含基础的依赖库,只需要 npm install就可以安装,让我们不需要为了编辑或者一些其...

木筏笔歆 ⋅ 今天 ⋅ 0

【微信小程序开发实战】0x00.开发前准备工作

写在开始 本人资深后端码农一枚,近期项目需求,接触到了微信小程序,将学习过程整理成文分享给小伙伴们,由于是边学边整理难免有表述不对的地方,望大家及时指正,感谢。 本人微信号: dream...

dreamans ⋅ 今天 ⋅ 0

linux redis的安装和php7下安装redis扩展

安装redis服务器 (1)下载安装包: $ wget http://download.redis.io/releases/redis-2.8.17.tar.gz (2)编译程序: $ tar xzf redis-2.8.17.tar.gz $ cd redis-2.8.17 $ make $ cd src &&......

concat ⋅ 今天 ⋅ 0

Guava EventBus源码解析

一、EventBus使用场景示例 Guava EventBus是事件发布/订阅框架,采用观察者模式,通过解耦发布者和订阅者简化事件(消息)的传递。这有点像简化版的MQ,除去了Broker,由EventBus托管了订阅&...

SaintTinyBoy ⋅ 今天 ⋅ 0

http怎么做自动跳转https

Apache 版本 如果需要整站跳转,则在网站的配置文件的<Directory>标签内,键入以下内容: RewriteEngine on RewriteCond %{SERVER_PORT} !^443$ RewriteRule ^(.*)?$ https://%{SERVER_NAME......

Helios51 ⋅ 今天 ⋅ 0

Python爬虫,抓取淘宝商品评论内容

作为一个资深吃货,网购各种零食是很频繁的,但是能否在浩瀚的商品库中找到合适的东西,就只能参考评论了!今天给大家分享用python做个抓取淘宝商品评论的小爬虫! 思路 我们就拿“德州扒鸡”...

python玩家 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部