【问题标题】:Instantiating a constructor with parameters in an internal class with reflection使用反射在内部类中实例化带有参数的构造函数
【发布时间】:2010-11-02 11:41:57
【问题描述】:

我有一些类似的东西:

object[] parameter = new object[1];
parameter[0] = x;
object instantiatedType =
Activator.CreateInstance(typeToInstantiate, parameter);

internal class xxx : ICompare<Type>
{
    private object[] x;

    # region Constructors

    internal xxx(object[] x)
    {
        this.x = x;
    }

    internal xxx()
    {
    }

    ...
}

我得到:

抛出异常:System.MissingMethodException:找不到类型“xxxx.xxx”的构造函数..

有什么想法吗?

【问题讨论】:

  • 我原本以为 parameter 是你传递为 x 的东西。但是,我刚刚意识到这可能不是您的意思,并且查看其他答案,似乎我并不孤单。如果这是正确的,我建议将parameter 重命名为parameters。或者更好的是,完全不用parameterActivator.CreateInstance(typeToInstantiate, new object[]{x})

标签: c# reflection


【解决方案1】:

问题在于Activator.CreateInstance(Type, object[]) 不考虑非公共构造函数。

例外情况

MissingMethodException: 没有匹配 找到公共构造函数。

这很容易通过将构造函数更改为publicvisibility;然后代码就可以正常工作了。

这是一种解决方法(经过测试):

 BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
 CultureInfo culture = null; // use InvariantCulture or other if you prefer
 object instantiatedType =   
   Activator.CreateInstance(typeToInstantiate, flags, null, parameter, culture);

如果您只需要无参数构造函数,这也可以:

//using the overload: public static object CreateInstance(Type type, bool nonPublic)
object instantiatedType = Activator.CreateInstance(typeToInstantiate, true)

【讨论】:

  • 我对此进行了测试,并认为值得一提的是,此方法仅适用于非公共构造函数。要使其适用于公共和非公共构造函数,请将 BindingFlags 更改为 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
  • 另外你不必使用对象,你可以这样使用它:YourType instantiatedType = (YourType)Activator.CreateInstance(typeof(YourType), true)
【解决方案2】:

(测试成功)

object instantiatedType =
   Activator.CreateInstance(typeToInstantiate,
   System.Reflection.BindingFlags.NonPublic |
     System.Reflection.BindingFlags.Instance,
   null, new object[] {parameter}, null);

这里解决了两个问题:

  • new object[] {parameter} 帮助它处理将object[] 作为采用params object[] 参数的方法的单个 参数传递的问题
  • BindingFlags 有助于解析非公共构造函数

(两个nulls 与binder 相关;默认的binder 行为符合我们的要求)

【讨论】:

  • 好像`Activator.CreateInstance`无法判断两个接受不同类型的单参数构造函数的区别……
  • 这种运行Activator.CreateInstance() 的方法确实使封装变得无关紧要。真的很不错!
【解决方案3】:

您需要调用a different overload of Activator.CreateInstance 以传递nonPublicBindingFlags 参数。

我发现所有这些CreateInstance 重载都很笨拙;我更喜欢做的是:

  1. 致电typeToInstantiate.GetConstructor(),传递BindingFlags.NonPublic
  2. 调用ConstructorInfo.Invoke,将构造函数参数传递给它

【讨论】:

    【解决方案4】:

    改成

    Activator.CreateInstance(typeToInstantiate,new object[] { parameter });
    

    这是因为您的构造函数还需要一个对象数组,而激活器已经将其拆分为单独的对象

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      • 2017-04-07
      相关资源
      最近更新 更多