dynamic动态应用-静态成员的动态封装类

静态成员的动态封装类

dynamic dynamic = new StaticMemberDynamicWrapper(typeof(string));
// 动态调用静态方法
var r = dynamic.Concat("A", "B");
Console.WriteLine(r);
if (r.Contains("A"))
{
Console.WriteLine(\("{r} Contains A"); } else { Console.WriteLine(\)"{r} Not Contains A");
}

/// <summary>
/// 静态成员的动态封装类
/// </summary>
internal sealed class StaticMemberDynamicWrapper : DynamicObject
{
    private readonly TypeInfo _typeInfo;
    public StaticMemberDynamicWrapper(Type type)
    {
        _typeInfo = type.GetTypeInfo();
    }
    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return _typeInfo.DeclaredMembers.Select(s => s.Name);
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = null;
        var field = FindField(binder.Name);
        if (field != null)
        {
            result = field.GetValue(null);
            return true;
        }
        var prop = FindProperty(binder.Name, true);
        if (prop != null)
        {
            result = prop.GetValue(null, null);
            return true;
        }
        return false;
    }
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        var field = FindField(binder.Name);
        if (field != null)
        {
            field.SetValue(null, value);
            return true;
        }
        var prop = FindProperty(binder.Name, false);
        if (prop != null)
        {
            prop.SetValue(null, value, null);
            return true;
        }
        return false;
    }
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        MethodInfo method = FindMethod(binder.Name, args.Select(s => s.GetType()).ToArray());
        if (method == null)
        {
            result = null;
            return false;
        }
        result = method.Invoke(null, args);
        return true;
    }

    private MethodInfo FindMethod(string name, Type[] paramTypes)
    {
        return _typeInfo.DeclaredMethods.FirstOrDefault(x => x.Name == name
        && x.IsPublic && x.IsStatic && ParametersMatch(x.GetParameters(), paramTypes));
    }

    private bool ParametersMatch(ParameterInfo[] parameterInfos, Type[] paramTypes)
    {
        if (parameterInfos.Length != paramTypes.Length)
        {
            return false;
        }
        for (int i = 0; i < parameterInfos.Length; i++)
        {
            if (parameterInfos[i].ParameterType != paramTypes[i])
            {
                return false;
            }
        }
        return true;
    }

    private PropertyInfo FindProperty(string name, bool get)
    {
        if (get)
        {
            return _typeInfo.DeclaredProperties.FirstOrDefault(x => x.Name == name
             && x.GetMethod != null && x.GetMethod.IsPublic && x.GetMethod.IsStatic);
        }
        return _typeInfo.DeclaredProperties.FirstOrDefault(x => x.Name == name
        && x.SetMethod != null && x.SetMethod.IsPublic && x.SetMethod.IsStatic);
    }

    private FieldInfo FindField(string name)
    {
        return _typeInfo.DeclaredFields.FirstOrDefault(x => x.IsPublic && x.IsStatic && x.Name == name);
    }
}

动态参数类型

public ObservableCollection<DynamicParaRow> ItemsSourceData { get; private set; }

dynamic model = new DynamicParaModel();
DynamicParaRow row = new DynamicParaRow("name", model);
ItemsSourceData.Add(row);

// 属性动态变化
foreach (var row in ItemsSourceData)
{
    row.DynamicParaModel.PropertyName = item.ParaName;
    row.DynamicParaModel.PropertyValue = item.ParaValue;
}

public class DynamicParaRow : NotifyPropertyChangedEx
{
  public DynamicParaRow(string name, DynamicParaModel model)
  {
      IsCheck = false;
      PropertyName1 = name;
      DynamicParaModel = model;
  }

  /// <summary>
  /// 属性名称
  /// </summary>
  public string PropertyName1 { get; set; }

  private bool _isCheck;
  /// <summary>
  /// 是否可勾选
  /// </summary>
  public bool IsCheck
  {
      get { return _isCheck; }
      set { UpdateProperty(ref _isCheck, value); }
  }

  private DynamicParaModel _dynamicParaModel;
  public DynamicParaModel DynamicParaModel
  {
      get { return _dynamicParaModel; }
      set { UpdateProperty(ref _dynamicParaModel, value); }
  }

}
/// <summary>
/// 动态参数类型
/// </summary>
public class DynamicParaModel : DynamicObject, INotifyPropertyChanged
{
  /// <summary>
  /// 属性名称
  /// </summary>
  public string PropertyName { get; set; }
  private object _propertyValue;
  /// <summary>
  /// 属性值
  /// </summary>
  public object PropertyValue
  {
      get { return _propertyValue; }
      set
      {
          _propertyValue = value;
          _properties[PropertyName] = value;

          OnPropertyChanged(PropertyName);
      }
  }

  readonly Dictionary<string, object> _properties = new Dictionary<string, object>();

  public void Delete(string propertyName)
  {
      if (_properties.ContainsKey(propertyName))
      {
          _properties.Remove(propertyName);
      }
  }

  public override bool TrySetMember(SetMemberBinder binder, object value)
  {
      if (_properties.Keys.Contains(binder.Name))
      {
          _properties[binder.Name] = value;
      }
      else
      {
          _properties.Add(binder.Name, value);
      }

      return true;
  }
  public override bool TryGetMember(GetMemberBinder binder, out object result)
  {
      return _properties.TryGetValue(binder.Name, out result);
  }


  public event PropertyChangedEventHandler PropertyChanged;
  private void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
  {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

动态添加参数

dynamic的属性直接调用即可。若不知道属性,或属性是根据条件动态生成的,可以通过内置的Dictionary处理。

dynamic obj = new System.Dynamic.ExpandoObject();
string key = "Name";
WSCommFunc.SetDynamicProperty(obj, key, DateTime.Now);
Console.WriteLine("Name: " + GetDynamicProperty(obj, key));

using System;
using System.ComponentModel;
using System.Dynamic;

/// <summary>
/// 动态设置动态属性
/// </summary>
/// <param name="obj">ExpandoObject</param>
/// <param name="propertyName">属性名称</param>
/// <param name="value">属性值</param>
public static void SetDynamicProperty(dynamic obj, string propertyName, object value)
{
    var dic = (IDictionary<string, object>)obj;
    if (dic.ContainsKey(propertyName))
    {
        dic[propertyName] = value;
    }
    else
    {
        dic.Add(propertyName, value);
    }
}
/// <summary>
/// 动态获取动态属性值
/// </summary>
/// <param name="obj">ExpandoObject</param>
/// <param name="propertyName">属性名称</param>
/// <returns></returns>
public static object GetDynamicProperty(dynamic obj, string propertyName)
{
    if (obj is IDictionary<string, object> dic && dic.TryGetValue(propertyName, out object value))
    {
        return value;
    }
    return default;
}
posted @ 2021-01-20 20:26  wesson2019  阅读(113)  评论(0编辑  收藏  举报