【问题标题】:Activator.CreateInstance with private sealed classActivator.CreateInstance 与私有密封类
【发布时间】:2009-01-13 17:47:57
【问题描述】:

我正在尝试新建一个 LocalCommand 实例,它是 System.Data.SqlClient.SqlCommandSet 的私有类。我似乎能够很好地获取类型信息:

Assembly sysData = Assembly.Load("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
localCmdType = sysData.GetType("System.Data.SqlClient.SqlCommandSet+LocalCommand");

但是当我尝试实例化它时,Activator.CreateInstance 会抛出异常:

object item = Activator.CreateInstance(localCmdType,
  new object[] { commandText, parameters, num7, commandType });

System.MissingMethodException:找不到类型“System.Data.SqlClient.SqlCommandSet+LocalCommand”的构造函数。

构造函数参数与我在 Reflector 中看到的签名相匹配。是否正在新建一个具有内部 ctor 的私有类,支持不同的 CreateInstance 重载或什么?

【问题讨论】:

    标签: c# reflection ado.net


    【解决方案1】:

    我的第一个想法是使用ConstructorInfo constructorInfo = Type.GetConstructor() 获取ConstructorInfo,然后使用constructorInfo.Invoke()。我怀疑Activator.CreateInstance 使得调用你通常无法访问的构造函数变得很困难,尽管我不记得自己尝试过。

    【讨论】:

    • 文档说 CreateInstance 在 2.0sp1 之前只调用公共构造函数。在那之后,还有一堆必要的权限。
    • 对 GetConstructor() 的良好调用,确实有效。考虑到 GetConstructor 调用看起来与 Activator.CreateInstance() 重载之一非常相似,我觉得很奇怪。
    【解决方案2】:

    我让它这样工作:

    using System;
    using System.Reflection;
    
    class Test
    {
        public String X { get; set; }
    
        Test(String x)
        {
            this.X = x;
        }
    }
    
    class Program
    {
        static void Main()
        {
            Type type = typeof(Test);
    
            ConstructorInfo c = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, 
                null, new Type[] { typeof(String) }, null);
    
            Object o = c.Invoke(new Object[] { "foo" });
        }
    }
    

    诀窍是专门使用GetConstructor 跟踪构造函数,而不是尝试在GetConstructors 的结果中找到它。去图吧。

    【讨论】:

    • 这可能是 PCL 中没有的吗?
    【解决方案3】:

    我的回复可能有点晚,但我遇到了适合此主题的类似问题。
    我想使用Activator.CreateInstance 实例化一个非公共构造函数并为其传递参数。

    public class Node
    {
        string name;
        Node parent;
    
        protected Node(string name,Node parent)
        {
           this.name = name;
           this.parent = parent;
        }
    
        public static Node Create(string name,Node parent)
        {
           Node result = Activator.CreateInstance(
             type: typeof(Node),
             bindingAttr: BindingFlags.Instance  | BindingFlags.NonPublic,
             binder: null, //default binder
             args: new object[] { name, parent },
             culture: null);
           return (Node)result;
        }
    }
    

    棘手的部分是绑定标志。

    我的第一反应是使用BindingFlags.CreateInstance | BindingFlags.NonPublic,但这导致抛出异常:MissingMethodException Constructor on type 'Node' not found.

    【讨论】:

    • 这对我来说因您描述的错误而失败,但奇怪的是,Andrew Hare 的答案确实有效,即使两个答案共享相同的绑定标志。
    • 根本行不通。正如 Jerther 所说,Andrew Hare 的回答确实如此。
    • 对我来说就像一个魅力!我也尝试使用BindingFlags.CreateInstance | BindingFlags.NonPublic 并收到相同的错误消息。将其更改为 BindingFlags.Instance | BindingFlags.NonPublic 使其工作!
    【解决方案4】:

    技巧是确保使用正确的CreateInstance重载:

    // WRONG
    ... Activator.CreateInstance(
           type,
           BindingFlags.Instance
           | BindingFlags.NonPublic
        );
    

    这将调用params 重载,默认为Instance | Public | CreateInstance,并且您的绑定标志将作为参数传递给构造函数,给出模糊的MissingMethodException

    此外,如果您不确定构造函数的可见性,请使用Instance | Public | NonPublic

    // right
    ... Activator.CreateInstance(
           type,
           BindingFlags.Instance
           | BindingFlags.Public
           | BindingFlags.NonPublic,
           null,
           new object[] { }, // or your actual constructor arguments
           null
        );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 2021-12-15
      相关资源
      最近更新 更多