欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-12 23:06:52
c#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种...

c#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种动态方法的实现,看起来有点javascript的对象味道:

1) 定义一个委托,参数个数可变,参数都是object类型:这里的委托多有个dynamic参数,代表调用这个委托的动态对象本身。

public delegate object mydelegate(dynamic sender, params object[] pms);

2) 定义一个委托转载对象,因为dynamic对象不能直接用匿名方法,这里用对象去承载:

public class delegateobj
  {
    private mydelegate _delegate;

    public mydelegate callmethod
    {
      get { return _delegate; }
    }
    private delegateobj(mydelegate d)
    {
      _delegate = d;
    }
    /// <summary>
    /// 构造委托对象,让它看起来有点javascript定义的味道.
    /// </summary>
    /// <param name="d"></param>
    /// <returns></returns>
    public static delegateobj function(mydelegate d)
    {
      return new delegateobj(d);
    }
  }

3) 定义一个动态对象:

public class dynobj : dynamicobject
  {
    //保存对象动态定义的属性值
    private dictionary<string, object> _values;
    public dynobj()
    {
      _values = new dictionary<string, object>();
    }
    /// <summary>
    /// 获取属性值
    /// </summary>
    /// <param name="propertyname"></param>
    /// <returns></returns>
    public object getpropertyvalue(string propertyname)
    {
      if (_values.containskey(propertyname) == true)
      {
        return _values[propertyname];
      }
      return null;
    }
    /// <summary>
    /// 设置属性值
    /// </summary>
    /// <param name="propertyname"></param>
    /// <param name="value"></param>
    public void setpropertyvalue(string propertyname,object value)
    {
      if (_values.containskey(propertyname) == true)
      {
        _values[propertyname] = value;
      }
      else
      {
        _values.add(propertyname, value);
      }
    }
    /// <summary>
    /// 实现动态对象属性成员访问的方法,得到返回指定属性的值
    /// </summary>
    /// <param name="binder"></param>
    /// <param name="result"></param>
    /// <returns></returns>
    public override bool trygetmember(getmemberbinder binder, out object result)
    {
      result = getpropertyvalue(binder.name);
      return result == null ? false : true;
    }
    /// <summary>
    /// 实现动态对象属性值设置的方法。
    /// </summary>
    /// <param name="binder"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public override bool trysetmember(setmemberbinder binder, object value)
    {
      setpropertyvalue(binder.name, value);
      return true;
    }
    /// <summary>
    /// 动态对象动态方法调用时执行的实际代码
    /// </summary>
    /// <param name="binder"></param>
    /// <param name="args"></param>
    /// <param name="result"></param>
    /// <returns></returns>
    public override bool tryinvokemember(invokememberbinder binder, object[] args, out object result)
    {
      var thedelegateobj = getpropertyvalue(binder.name) as delegateobj;
      if (thedelegateobj == null || thedelegateobj.callmethod == null)
      {
        result = null;
        return false;
      }
      result = thedelegateobj.callmethod(this,args);
      return true;
    }
    public override bool tryinvoke(invokebinder binder, object[] args, out object result)
    {
      return base.tryinvoke(binder, args, out result);
    }
  }

应用测试代码:

dynamic theobj = new dynobj();
      theobj.aaa = "this is a test";//动态属性
      //动态方法,这里不能没法定义参数,调用的时候可以是任意多参数,具体参数类型和含义就只能自己去小心处理了.
      theobj.show = delegateobj.function((s, pms) =>
      {
        if (pms != null && pms.length > 0)
        {
          messagebox.show(pms[0].tostring() + ":" + s.aaa);
        }
        else
        {
          messagebox.show(s.aaa);
        }
        return null;
      }
      );
      
theobj.show("hello");

虽然看起来上面有点js定义对象方法的味道,但由于c#是静态语言,提供的动态模拟机制还是有限的,看起来是动态,但所有的值存放和方法都需要自己写代码去处理.

上面代码在vs2010,windows 2008 server,框架4.0 上测试ok.

以上这篇c#动态对象(dynamic)详解(实现方法和属性的动态)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。