C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下)

接上文:C# Dynamic关键字之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(上)

为什么TryXXX方法没有被调用??

将DynamicProduct 中的name修饰符改为private:

private string name;

可以在TrySetMember方法中设置断点,再次运行:

为什么访问修饰符是Public不调用TrySetMember,是Private 就调用了呢??

难道是因为private抛出了异常吗??

再次看看Msdn对此的TrySetMember方法的解释:

Msdn备注

…………….动态语言运行库 (DLR) 将首先使用语言联编程序在类中查找属性的静态定义。 如果没有此类属性,DLR 调用 TrySetMember 方法。

问题的原因是这样的:首先DLR 使用语言联编程序在类中查找name的静态定义,

因为name是public,所以查找到了,然后返回,不会去调用TrySetMember方法了,

但是如果name是private,那么联编程序在类中没找到name的静态定义,于是DLR尝试调用TrySetMember方法。

修改TrySetMember方法如下:

代码如下:

public override bool TrySetMember(SetMemberBinder binder, object value)
{
    Console.WriteLine("TrySetMember被调用了,Name:{0}", binder.Name);
    bool result = base.TrySetMember(binder, value);

return true;
}

运行,可以发现不会抛出异常了:

总结:首先DLR会尝试查找属性的静态定义,如果没有找到则会调用相应的TryXXX 方法,如果TryXXX方法返回false,代表TryXXX方法运行失败,DLR随后会抛出异常。

为了验证是不是这样,将DynamicProduct中属性的静态定义全部注释掉,并且TryXXX方法全部返回True。完整的代码如下:

代码如下:

class DynamicProduct : DynamicObject
{
    #region dynamicProduct 的一些属性的静态定义

//private string name;
        //public int Id { get; set; }

//public void ShowProduct()
        //{
        //    Console.WriteLine("Id={0} ,Name={1}", Id, name);
        //}

#endregion

#region Override DynamicObject 的方法

public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        Console.WriteLine("TryGetMember被调用了,Name:{0}", binder.Name);
        bool tryResult = base.TryGetMember(binder, out result);

return true;
    }

public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        Console.WriteLine("TrySetMember被调用了,Name:{0}", binder.Name);
        bool tryResult = base.TrySetMember(binder, value);

return true;
    }

public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
    {
        Console.WriteLine("TryInvoke被调用了");
        bool tryResult = base.TryInvoke(binder, args, out result);

return true;
    }

public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        Console.WriteLine("TryInvokeMember被调用了,Name:{0}", binder.Name);
        bool tryResult = base.TryInvokeMember(binder, args, out result);

return true;
    }

#endregion
}

Main方法不变:


代码如下:

static void Main(string[] args)
{
    dynamic dynProduct = new DynamicProduct();

dynProduct.name = "n1"; //调用TrySetMember方法
    dynProduct.Id = 1;
    dynProduct.Id = dynProduct.Id + 3;
    dynProduct.ShowProduct();

Console.ReadLine();
}

运行,结果如下:

d.P3 = d.M1(d.P1, d.M2(d.P2));

按照从左到右,从里到外的原则。

1:先调用d.P1,DLR会尝试调用d 的GetMetaObject 方法,此方法返回一个MyMetaObject对象。

接着DLR知道你调用的是一个属性,于是它调用返回的MyMetaObject对象的BindGetMember 方法,

输出为GetMember of property P1

2:调用d.P2,和调用d.P1 一样.

3:调用d.M2,同样DLR调用d的GetMetaObject方法,返回一个MyMetaObject对象,接着调用返回对象的BindInvokeMember 方法。

(0)

相关推荐

  • C#探秘系列(四)——GetHashCode,ExpandoObject

    这篇继续分享下GetHashCode和ExpandoObject这两个比较好玩的方法. 一:GetHashCode 从MSDN上可以看到的解释是:用作特定类型的哈希函数,也就是说任何对象的实例都会有一个int32类型的HashCode,并且存放在FCL中的HashCollection中,废话不说,看个例子: 从图中可以看到,两个类实例的hashcode不同,说明二者不是同一个引用,也就有了不同的hashcode,利用这个特性,我们是不是可以生成一些随机数字呢? 1:在for循环中用random生

  • C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(上)

    ExpandoObject:表示一个对象,该对象包含可在运行时动态添加和移除的成员. 复制代码 代码如下: dynamic dynEO = new ExpandoObject();dynEO.number = 10;dynEO.Increment = new Action(() => { dynEO.number++; }); Console.WriteLine(dynEO.number);dynEO.Increment();Console.WriteLine(dynEO.number); dy

  • C#探秘系列(二)——IsXXX 系列方法

    不知道有人做没做过对日外包,如果做过的话,那么对vb.net应该非常熟悉了,当年我刚毕业的时候也做过四个月的外包,那种日子简直不是人过的,就连大楼下面买珠宝的阿姨都说,这些孩子,只看过他们上班,就没见过他们下班,不过有一点好,有个QA的小姑娘天天下午6点教我们倭瓜语,现在还在勾搭中...    好了,现在我们看看需求. 一: 如何判断"a"是不是数字类型. ①:在C#中我们可能会用TryParse来判断当前的"a"是否为整数. 复制代码 代码如下: static v

  • C#探秘系列(一)——ToDictionary,ToLookup

    这个系列我们看看C#中有哪些我们知道,但是又不知道怎么用,又或者懒得去了解的东西,比如这篇我们要介绍的toDictionary和ToLookup. 从图中我们看到有四个ToXXX的方法,其中ToArray和ToList,我想大家用的是非常非常多,但是ToDictionary和ToLookup不见得有多少人用了,但不能否认的是这些方法确实很有用. 不多废话了,直接如主题,我们有这样的一个实体,包含:票号,订单号,备注. 复制代码 代码如下: class Ticket    {        ///

  • C#探秘系列(三)——StackTrace,Trim

    一: Environment.StackTrace 可能我们看到最多的就是catch中的e参数,里面会有一个StackTrace,然后不可否认的这玩意太有用了,它会把调用堆栈中的信息输出出来,有了它,我们就可以快速的知道运行代码的执行流并且快速的定位到问题. 有时候我们会遇到这样两个问题: ①:线上的bug在本地不能重现. ②:由于太多的多态,设计模式,程序员反而对线上的代码执行流向会搞的稀里糊涂的. 为了搞清楚并解决这两个问题,我们看生产日志的时候很在乎代码的执行流以及想获取当前上下文的可疑变

  • C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下)

    接上文:C# Dynamic关键字之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(上) 为什么TryXXX方法没有被调用?? 将DynamicProduct 中的name修饰符改为private: private string name; 可以在TrySetMember方法中设置断点,再次运行: 为什么访问修饰符是Public不调用TrySetMember,是Private 就调用了呢?? 难道是因为private抛出了异常吗?? 再次看看Msdn对

  • C#使用Json.Net对JSON与对象的序列化与反序列化

    目录 一.使用Json.Net 1.把DataTable转换成json格式,使用最新Json.Net DLL ,已经内置转换器. 2.对Json.Net序列化和反序列化的控制 二.空值的处理 三.默认值的处理 四.忽略某些属性 五.支持非公共成员 六.日期处理 1.使用IsoDateTimeConverter 和 JavaScriptDateTimeConverter标准格式 1.如果你要序列化的日期格式是统一的,可以考虑如下方式 2.如果想要不同的日期类型成员序列化后,以不同的形式显示. 2.

  • HTML5视频播放标签video和音频播放标签audio标签的正确用法

    如何嵌入视频和音频 在网页里嵌入HTML5音频播放器和视频播放器的方法非常简单: <video src="//www.jb51.net/~j/theora_testsuite/320x240.ogg" controls autoplay loop> Your browser does not support the <code>video</code> element. </video> 上面这个例子显示了如何播放一个视频文件,并露出视频

  • Asp.net core利用dynamic简化数据库访问

    今天写了一个数据库的帮助类,代码如下. public static class DbEx { public static dynamic ReadToObject(this IDataReader reader) { var obj = new DbObject(); for (int i = 0; i < reader.FieldCount; i++) { obj[reader.GetName(i)] = new DbField() { DbData = reader[i] }; } retu

  • 深入C# 4.0 新特性dynamic、可选参数、命名参数的详细介绍

    1.dynamic ExpandoObject熟悉js的朋友都知道js可以这么写 : 复制代码 代码如下: var t = new Object(); t.Abc = 'something'; t.Value = 243; 现在这个js动态语言的特性,我们也可以在c#中使用了,前提是将一个变量声明为ExpandoObject类型.如下例: 复制代码 代码如下: static void Main(string[] args) { dynamic t = new ExpandoObject(); t

  • C#动态对象(dynamic)详解(实现方法和属性的动态)

    C#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种动态方法的实现,看起来有点javascript的对象味道: 1) 定义一个委托,参数个数可变,参数都是object类型:这里的委托多有个dynamic参数,代表调用这个委托的动态对象本身. public delegate object MyDelegate(dynamic Sender, params object[] PMs

  • C#中dynamic关键字的正确用法(推荐)

    dynamic是FrameWork4.0的新特性.dynamic的出现让C#具有了弱语言类型的特性.编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性.比如,即使你对GetDynamicObject方法返回的对象一无所知,你也可以像如下那样进行代码的调用,编译器不会报错: dynamic dynamicObject = GetDynamicObject(); Console.WriteLine(dynamicObject.Name); Console.Writ

  • C#使用dynamic类型访问JObject对象

    dynamic是C#里面的动态类型,可在未知类型的情况访问对应的属性,非常灵活和方便. 使用Json.Net可以把一个Json字符串转换成一个JObject对象,如果有已知强类型,如果有已知对应的强类型,可以直接转成对应的类型.但如果没有,要访问Json里面对应的数据的时候,就显得比较麻烦.我们可以借助DynamicObject来访问对应的属性. DynamicObject 我们要创建一个动态类,用于访问JObject,代码如下: public class JObjectAccessor : D

随机推荐