繁体   English   中英

内部类和公共构造函数 - 为什么它与Activator.CreateInstance一起使用?

[英]Internal classes and public constructors - why does it work with Activator.CreateInstance?

我想通过Activator.CreateInstance(...)创建一些类的实例。 所有类都继承相同的抽象类。 构造函数有一个参数。

类和构造函数不应该是公共的。

这是我想要的代码(但不是得到):

internal abstract class FooAbstract
{
    protected Bar MyProperty { get; set; }

    // Constructor is only need in concreat classes of FooAbstract
    protected FooAbstract(Bar barProperty)
    {
        MyProperty = barProperty;
    }
}

internal class Foo : FooAbstract
{
    // Internal is enough, public is not necessary
    internal Foo(Bar barProperty) 
        : base(barProperty)
    {
}

// Many more Foo´s ...

internal class Creator()
{
    private object CreateAFoo<T>() where T : FooAbstract
    {
        T someFoo = (T)Activator.CreateInstance(typeof(T), barProperty);
    }
}

但是这会抛出一个Constructor on type 'Foo' not found的异常Constructor on type 'Foo' not found

当我将FooAbstract Foo构造函数更改为public一切都会好的(类保持internal !)。

所以我可以理解Activator.CreateInstance(...)需要公共访问(他来自包外),但为什么剩余的内部类可以实现呢?

到目前为止,我认为当类是内部的 构造函数是公共的时 ,它将与内部类相同 构造函数也是内部的 (对于一种层次化的访问层)...但这似乎是错误的!

有人可以帮我理解这里发生了什么 - 为什么内部班级的公共建设者确实有效?

您需要为反射指定BindingFlags才能找到它:

(T)Activator.CreateInstance(typeof(T),
    BindingFlags.Instance | BindingFlags.NonPublic,
    null
    new object[] { barProperty },
    null);

现在,在这种情况下,您需要构建一个object[]因为它不是一个params

正如Matthew Watson所说,我应该澄清反思的运作方式。 也许更具体的修饰语。 它们[修饰符]不是为了真正的保护而构建的。 它们用于确定在使用类型时可用的API。

然而,反射直接在修改器之外起作用。 如果它是public - 然后通过反思它是public 层次结构无关紧要。 请记住,反射实际上可以访问private成员。 我知道,我之前不得不破解类似的东西。

此外,构造函数不继承class的修饰符。 默认构造函数 - 如果您没有定义它,由编译器生成 - 始终是 public

激活器使用反射来调用构造函数的正确实例。 默认情况下,它可能只针对公共类成员。 正如neoistheone所说,你可以通过在激活方法调用上设置标志来改变它寻找构造函数的方式。 该方法的反编译代码如下所示。

[SecuritySafeCritical]
[MethodImpl(MethodImplOptions.NoInlining)]
public static object CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes)
{
    if (type == null)
    {
        throw new ArgumentNullException("type");
    }
    if (type is TypeBuilder)
    {
        throw new NotSupportedException(Environment.GetResourceString("NotSupported_CreateInstanceWithTypeBuilder"));
    }
    if ((bindingAttr & (BindingFlags)255) == BindingFlags.Default)
    {
        bindingAttr |= (BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance);
    }
    if (activationAttributes != null && activationAttributes.Length > 0)
    {
        if (!type.IsMarshalByRef)
        {
            throw new NotSupportedException(Environment.GetResourceString("NotSupported_ActivAttrOnNonMBR"));
        }
        if (!type.IsContextful && (activationAttributes.Length > 1 || !(activationAttributes[0] is UrlAttribute)))
        {
            throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonUrlAttrOnMBR"));
        }
    }
    RuntimeType runtimeType = type.UnderlyingSystemType as RuntimeType;
    if (runtimeType == null)
    {
        throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type");
    }
    StackCrawlMark stackCrawlMark = StackCrawlMark.LookForMyCaller;
    return runtimeType.CreateInstanceImpl(bindingAttr, binder, args, culture, activationAttributes, ref stackCrawlMark);
}

RuntimeType是一个反射类型,这里有一个堆栈溢出问题: C#中System.Type和System.RuntimeType之间有什么区别?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM