zoukankan      html  css  js  c++  java
  • ExpandoObject, DynamicObject, DynamicMetaObject

    ExpandoObject

    由于ExpandObject的先天不足(无特征性):

    1. ExpandObject不能用于太复杂的对象。

    ExpandObject最好还是作为简单的数据容器,不要弄得过于复杂,甚至包含有函数处理。

    2.ExpandObject的使用范围必须要短

    范围短的意思是,产生和使用ExpandObject的代码的路径必须要短(主要是函数调用路径)。如果你正在使用一个ExpandObject对象,查看产生这个ExpandObject的地方,发现分散在好几个函数之中,还有嵌套的话,那么这个ExpandObject是非常难于维护的。

    3. ExpandObject的使用场合最好贴近程序的终端。

    比如在MVC中的ViewBag, 就是一个好的例子。ViawBag用于生成页面, 而页面就是MVC程序的终端了。到了终端,ExpandObject也就不能祸害它人了。
    正是由于ExpandObject的无特征性,什么都可以做,所以容易导致滥用。

        static void Main(string[] args)
        {
            Console.WriteLine("-------1.简便存储-------");
            {
                dynamic expando = new ExpandoObject();
                expando.First = "value set dynamically";
                expando.Second = 2;
                Console.WriteLine(expando.First);
                Console.WriteLine(expando.Second);
            }
    //-------1.简便存储-------
    //value set dynamically
    //2
            
            Console.WriteLine("-------2.用字典方式存储-------");
            {
                dynamic expando = new ExpandoObject();
                IDictionary<string, object> dictionary = expando;
                expando.First = "value set dynamically";
                Console.WriteLine(dictionary["First"]);
    
                dictionary["Second"] = "value set with dictionary";
                Console.WriteLine(expando.Second);
            }
    //-------2.用字典方式存储-------
    //value set dynamically
    //value set with dictionary
            
            Console.WriteLine("-------3.用委托伪造ExpandoObject的方法-------");
            {
                //Func<int, int> result = x => x + 1;
                dynamic expando = new ExpandoObject();
                expando.AddOne = (Func<int, int>)(x => x + 1);
                Console.Write(expando.AddOne(10));
    
            }
            Console.Read();
    
        }
    //-------3.用委托伪造ExpandoObject的方法-------
    //11
    

    DynamicObject

    DynamicObject有个构造函数,但是protected, 也就是我们没有办法直接实例化来使用它。只能是通过继承来构造DynamicObject的对象。

    同时DynamicObject中很很多标记为Virtual的方法,比如:

    public virtual bool TryGetMember(GetMemberBinder binder, out object result);
    
    public virtual bool TrySetMember(SetMemberBinder binder, object value);
    

    案例1(错误示范):

    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
    }
    
    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();
    }
    
    //-------DynamicObject-------
    //Id=4 ,Name=n1
    //n1
    

    没有执行TryXXX....

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

    private string name;

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

    image

    clip_image002

    clip_image004

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

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

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

    Msdn****备注

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

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

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

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

    案例2:(正确示范)

     public class DynamicProduct : DynamicObject
    {
        Dictionary<string, Object> _dic = new Dictionary<string, object>();
    
        //设置为 public ,赋值时,就不会访问 TrySetMember
        //private object name { get; set; }
        //public int Id { get; set; }
    
        //public void ShowProduct()
        //{
        //    Console.WriteLine("Id={0} ,Name={1}", Id, name);
        //}
    
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            Console.WriteLine("TryGetMember被调用了,Name:{0}", binder.Name);
            var name = binder.Name;
            return _dic.TryGetValue(name, out result);
        }
    
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            Console.WriteLine("TrySetMember被调用了,Name:{0}", binder.Name);
            _dic[binder.Name] = value;
            return true;
        }
    }
    
    static void Main(string[] args)
    {
         dynamic dynProduct = new DynamicProduct();
    
        dynProduct.name = "n1"; //调用TrySetMember方法
        //dynProduct.Id = 1;
        //dynProduct.Id = dynProduct.Id + 3;
        //dynProduct.ShowProduct();
    
        Console.WriteLine(dynProduct.name);
    
        Console.ReadLine();
    }
    
    //output:
    //TrySetMember被调用了,Name:name
    //TryGetMember被调用了,Name:name
    //n1
    

    DynamicMetaObject

    未完...

    参考:

    理解C# 4 dynamic(3) – DynamicObject的使用

    浅谈Dynamic 关键字系列之三(下):ExpandoObject,DynamicObject,DynamicMetaObject

  • 相关阅读:
    操作正则表达式的公共类
    验证码类
    强制转化常用函数
    实现Base64编码与其它编码转换的类
    关于任务管理器踩过的坑,程序员必看!
    每次找Internet选项感到抓狂?一键打开!
    教你避过安装TensorFlow的两个坑
    HTML中id与name的通俗区别
    VS code代码对齐快捷键
    form和table的区别
  • 原文地址:https://www.cnblogs.com/tangge/p/14716420.html
Copyright © 2011-2022 走看看