【问题标题】:How do you dynamically Invoke a constructor of an object without knowing all of the parameters?如何在不知道所有参数的情况下动态调用对象的构造函数?
【发布时间】:2015-10-29 23:41:47
【问题描述】:

这是我目前所拥有的:

var constructor = typeof (ParentModel).GetConstructor(FieldInformationTypes);
var model = (ParentModel)constructor.Invoke(Values.Values.ToArray());
return model;

和FieldInformationTypes(在具有上述代码的类的超类中)

protected Type[] FieldInfoTypes;
public Type[] FieldInformationTypes
{
    get
    {
        if (FieldInfoTypes == null) return FieldInfoTypes;

        var memberTypes = (
            from fieldInfo in FieldInformation
            select fieldInfo.MemberType).ToArray();

        FieldInfoTypes = (
            from memberType in memberTypes
            select memberType.GetType()).ToArray();

        return FieldInfoTypes;
    }
}

protected FieldInfo[] FieldInfos;
public FieldInfo[] FieldInformation
{
    get
    {
        // don't GetFields all the time
        if (FieldInfos != null) return FieldInfos;

        FieldInfos = typeof(T).GetFields(
            BindingFlags.Public |
            BindingFlags.NonPublic |
            BindingFlags.Instance);

        return FieldInfos;
    }
}

T 是我尝试动态创建的带有构造函数的类。

Values 只是stringsobjects 的字典,其中字符串是参数字段名称,值可以是任何值。

我知道使用命名参数,ParentModel 可以这样创建:

new ParentModel(
    children: _children,
    isResponsible: _isResponsible);

或者通过这种技术:

new ParentModel()
{
    Children = _children,
    IsResponsible = _isResponsible
};

这两种调用方法(在我的例子中是构造函数)的技术看起来都非常像哈希/字典。所以,我觉得应该可以通过字典动态调用方法。我的问题是:如何?

理想情况下,我希望能够通过执行以下操作来调用方法:

new MyObject(myDictionaryOfParameters.ToNamedParameter());

或者类似的东西。

【问题讨论】:

    标签: c# dynamic metaprogramming


    【解决方案1】:

    GetConstructor()返回的ConstructorInfo这样的扩展方法怎么样:

        public static object Invoke(this ConstructorInfo constructor, Dictionary<string, object> parameters)
        {
            List<object> parameterValues = new List<object>();
            foreach(var parameterInfo in constructor.GetParameters())
            {
                if (parameters.ContainsKey(parameterInfo.Name))
                    parameterValues.Add(parameters[parameterInfo.Name]);
                else
                    parameterValues.Add(null);
            }
            return constructor.Invoke(parameterValues.ToArray());
        }
    

    那么你就可以打这样的电话了:

    var constructor = typeof (ParentModel).GetConstructor(FieldInformationTypes);
    var model = (ParentModel)constructor.Invoke(Values);
    return model;
    

    【讨论】:

      【解决方案2】:

      假设在您的第一个示例中Values 是您的Dictionary&lt;string, object&gt;,那么您将无法正常工作。 Dictionaries 不保留顺序,因此您无法确定您从字典中获取的值是否与构造函数上的参数匹配。您可以改为使用GetParameters 方法来排列您的参数:

      var constructor = typeof (ParentModel).GetConstructor(FieldInformationTypes);
      var parameters = constructor.GetParameters();
      var model = (ParentModel)constructor.Invoke(parameters.Select(p => Values[p.Name]).ToArray());
      return model;
      

      使用命名参数不会将参数作为字典传递。编译器会将调用重写为正常的方法调用。此外,您的第二个示例是不向构造函数传递任何参数。

      new ParentModel()
      {
          Children = _children,
          IsResponsible = _isResponsible
      };
      

      这会调用默认构造函数并设置ChildrenIsResponsible 属性。这只是语法糖:

      var model new ParentModel();
      model.Children = _children;
      model.IsResponsible = _isResponsible;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-03
        相关资源
        最近更新 更多