简体   繁体   English

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

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

I want to create some instances of classes via Activator.CreateInstance(...) . 我想通过Activator.CreateInstance(...)创建一些类的实例。 All classes inherit same abstract class. 所有类都继承相同的抽象类。 The constructor has one parameter. 构造函数有一个参数。

Classes and constructors should not be public. 类和构造函数不应该是公共的。

This is what I want in code (but not get): 这是我想要的代码(但不是得到):

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);
    }
}

But this throws an Exception Constructor on type 'Foo' not found . 但是这会抛出一个Constructor on type 'Foo' not found的异常Constructor on type 'Foo' not found

When I change constructor of FooAbstract and Foo to public all will be fine (classes stay internal !). 当我将FooAbstract Foo构造函数更改为public一切都会好的(类保持internal !)。

So I can understood that Activator.CreateInstance(...) needs public access (he comes from outside the package), but why is this possible with remaining internal classes? 所以我可以理解Activator.CreateInstance(...)需要公共访问(他来自包外),但为什么剩余的内部类可以实现呢?

Until now I thought that when class is internal and constructor is public it would be the same as class is internal and constructor is also internal (to kind of hierarchic access layers) ... but this seems to be wrong! 到目前为止,我认为当类是内部的 构造函数是公共的时 ,它将与内部类相同 构造函数也是内部的 (对于一种层次化的访问层)...但这似乎是错误的!

Can somebody help me to understand what happened here - why public constructors in internal classes do work? 有人可以帮我理解这里发生了什么 - 为什么内部班级的公共建设者确实有效?

You need to specify the BindingFlags for reflection to find it: 您需要为反射指定BindingFlags才能找到它:

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

Now, in this case you do need to build an object[] because it's not a params . 现在,在这种情况下,您需要构建一个object[]因为它不是一个params

As Matthew Watson stated, I should clarify the way reflection works. 正如Matthew Watson所说,我应该澄清反思的运作方式。 And maybe more specifically modifiers. 也许更具体的修饰语。 They [modifiers] aren't built for real protection. 它们[修饰符]不是为了真正的保护而构建的。 They are built to determine the API that's available when you're using the types. 它们用于确定在使用类型时可用的API。

Reflection however, works directly off the modifier. 然而,反射直接在修改器之外起作用。 If it's public - then with reflection it's public . 如果它是public - 然后通过反思它是public It doesn't matter the hierarchy. 层次结构无关紧要。 Remember, reflection can actually access private members. 请记住,反射实际上可以访问private成员。 I know, I've had to hack a few things like that before. 我知道,我之前不得不破解类似的东西。

Further, constructors don't inherit the modifier of the class . 此外,构造函数不继承class的修饰符。 The default constructor - that's generated by the compiler if you don't define it - is always public . 默认构造函数 - 如果您没有定义它,由编译器生成 - 始终是 public

The activator uses reflection to invoke the proper instance of the constructor. 激活器使用反射来调用构造函数的正确实例。 It likely by default is looking only for public class members. 默认情况下,它可能只针对公共类成员。 As stated by neoistheone you can change the way it is looking for the constructor by setting flags on the activator method call. 正如neoistheone所说,你可以通过在激活方法调用上设置标志来改变它寻找构造函数的方式。 The decompiled code for that method looks like this. 该方法的反编译代码如下所示。

[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 is a reflected type there is a stack overflow question about it here: What's the difference between System.Type and System.RuntimeType in C#? RuntimeType是一个反射类型,这里有一个堆栈溢出问题: C#中System.Type和System.RuntimeType之间有什么区别?

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

相关问题 Activator.CreateInstance - 如何创建具有参数化构造函数的类的实例 - Activator.CreateInstance - How to create instances of classes that have parameterized constructors 为什么 Activator.CreateInstance&lt;&gt;() 找不到内部无参数构造函数? - Why can't Activator.CreateInstance<>() find an internal parameterless constructor? 如何为各种构造函数做Activator.CreateInstance? - How to do Activator.CreateInstance for various constructors? 为什么Activator.CreateInstance()在动态加载的程序集中失败? - Why does Activator.CreateInstance() fail in dynamically loaded assembly? 为什么我对Activator.CreateInstance的调用会间歇性地失败? - Why does my call to Activator.CreateInstance intermittently fail? Activator.CreateInstance:类的动态实例化 - Activator.CreateInstance: Dynamic Instantiation of Classes 为什么调用 Activator.CreateInstance 失败? - Why is this invocation of Activator.CreateInstance failing? 为什么不能让Activator.CreateInstance找到构造函数? - Why cant Activator.CreateInstance find the constructor? 如何Activator.CreateInstance一个没有构造函数的类型? - How to Activator.CreateInstance a type which have not constructors? Activator.CreateInstance MissingMethodException - Activator.CreateInstance MissingMethodException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM