zoukankan      html  css  js  c++  java
  • 浅谈Dynamic 关键字系列之三(上):ExpandoObject, DynamicObject, DynamicMetaObject

    ExpandoObject:表示一个对象,该对象包含可在运行时动态添加和移除的成员。

    dynamic dynEO = new ExpandoObject();
    dynEO.number = 10;
    dynEO.Increment = new Action(() => { dynEO.number++; });
    
    Console.WriteLine(dynEO.number);
    dynEO.Increment();
    Console.WriteLine(dynEO.number);
     

    dynEO.number 中number是动态添加属性。

    dynEO.Increment 中Increment 是动态添加的Action 委托。

     

    枚举ExpandoObject的所有成员:

    foreach (var property in (IDictionary<String, Object>)dynEO)
    {
         Console.WriteLine(property.Key + ": " + property.Value);
    }

    结果如下:

    clip_image002

    接收属性更改的通知:

    static void Main(string[] args)
    {
       ………
        ((INotifyPropertyChanged)dynEO).PropertyChanged += new PropertyChangedEventHandler(Program_PropertyChanged);
        dynEO.Name = "changed";
        dynEO.Name = "another";
    
        Console.ReadLine();
    }
    
    static void Program_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("属性{0} 已更改", e.PropertyName);
    }

    结果:

    clip_image002[5]

    System.Dynamic.DynamicObject:提供用于指定运行时的动态行为的基类

    新建类DynamicProduct,基本和Product类似:

    image

    可以看到继承了DynamicObject后,可以override 一大堆TryXXX的方法了。

    重点需要了解的是:

    假设sampleObject 就是dynamicObject

    TryGetMember

    在调用 int number = sampleObject.Number.时使用

    TrySetMember

    在调用sampleObject.Number = number 时使用

    TryInvoke

    在调用sampleObject(100) 时使用

    TryInvokeMember

    在调用sampleObject.someMethod(100) 时使用

     

    完整的代码如下:

    class DynamicProduct : DynamicObject
    {
        public string name;
        public int Id { get; set; }
    
        public void ShowProduct()
        {
            Console.WriteLine("Id={0} ,Name={1}", Id, name);
        }
    
        #region Override DynamicObject 的方法
    
        public override IEnumerable<string> GetDynamicMemberNames()
        {
            return base.GetDynamicMemberNames();
        }
    
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            Console.WriteLine("TryGetMember被调用了,Name:{0}", binder.Name);
            return base.TryGetMember(binder, out result);
        }
    
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            Console.WriteLine("TrySetMember被调用了,Name:{0}", binder.Name);
            return base.TrySetMember(binder, value);
        }
    
        public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
        {
            Console.WriteLine("TryInvoke被调用了");
            return base.TryInvoke(binder, args, out result);
        }
    
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            Console.WriteLine("TryInvokeMember被调用了,Name:{0}", binder.Name);
            return base.TryInvokeMember(binder, args, out result);
        }
    
        #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();
    }
     

    结果如下:

    clip_image002[7]

     

    理论上来说,应该输出:

    TrySetMember          :设置name字段

    TrySetMember          :设置Id属性

    TryGetMember          :获取Id属性

    TrySetMember          :设置Id属性

    TryInvokeMember      :调用ShowProduct方法

    Id =4 ,Name = n1

     

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

    下篇将解释这个问题,请持续关注..

  • 相关阅读:
    单调栈
    P1164 小A点菜
    P1156 垃圾陷阱
    P1140 相似基因
    P1136 迎接仪式
    P1133 教主的花园
    P1131 [ZJOI2007]时态同步
    P1130 红牌
    利用SQLite在android上实现增删改查
    利用SQLite在android上创建数据库
  • 原文地址:https://www.cnblogs.com/LoveJenny/p/2098578.html
Copyright © 2011-2022 走看看