C Dynamic Object of dynamic Detailed Explanation of of Implementation Method and Dynamic Attributes

  • 2021-12-05 07:05:46
  • OfStack

The attribute implementation of C # dynamic objects is relatively simple, and it is difficult to implement the dynamic method of dynamic language, because for dynamic objects, extension methods and anonymous methods cannot be used directly. Here, objects and delegates are used to simulate the implementation of this dynamic method, which looks a bit like javascript objects:

1) Define a delegate with variable number of parameters, all of which are object type: the delegate here has an dynamic parameter, which represents the dynamic object itself that calls the delegate.


public delegate object MyDelegate(dynamic Sender, params object[] PMs);

2) Define a delegate reprint object, because dynamic object cannot be directly used anonymous method, here use object to carry:


public class DelegateObj
  {
    private MyDelegate _delegate;

    public MyDelegate CallMethod
    {
      get { return _delegate; }
    }
    private DelegateObj(MyDelegate D)
    {
      _delegate = D;
    }
    /// <summary>
    ///  Construct the delegate object to make it look a little bit javascript Defined taste .
    /// </summary>
    /// <param name="D"></param>
    /// <returns></returns>
    public static DelegateObj Function(MyDelegate D)
    {
      return new DelegateObj(D);
    }
  }

3) Define a dynamic object:


public class DynObj : DynamicObject
  {
    // Save the property values dynamically defined by objects 
    private Dictionary<string, object> _values;
    public DynObj()
    {
      _values = new Dictionary<string, object>();
    }
    /// <summary>
    ///  Get the property value 
    /// </summary>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    public object GetPropertyValue(string propertyName)
    {
      if (_values.ContainsKey(propertyName) == true)
      {
        return _values[propertyName];
      }
      return null;
    }
    /// <summary>
    ///  Setting property values 
    /// </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>
    ///  Realize the method of accessing the attribute members of dynamic objects, and get the value of the specified attribute 
    /// </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>
    ///  Implement the method of setting the property value of a dynamic object. 
    /// </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>
    ///  Actual code executed when dynamic method calls of dynamic objects 
    /// </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);
    }
  }

Apply test code:


dynamic theObj = new DynObj();
      theObj.aaa = "this is a test";// Dynamic attribute 
      // Dynamic method, here can not be unable to define parameters, call can be any multiple parameters, specific parameter types and meanings can only be carefully handled .
      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");

Although it seems that Js defines object methods, because C # is a static language, the dynamic simulation mechanism provided is limited and looks dynamic, but all value storage and methods need to be handled by writing their own codes.

The above code tests OK on vs 2010, windows 2008 server, Framework 4.0.


Related articles: