简体   繁体   中英

Why can't Activator.CreateInstance<>() find an internal parameterless constructor?

I'm trying to create an instance of an object using Activator.CreateInstance<>(). The class used as a template has only one constructor which has no parameters but is internal. This shouldn't be an issue since that constructor is still accessible within the scope where CreateInstance is called. Yet, it throws the exception "No parameterless constructor defined for type...'.'". I made a new project to isolate it from any external factors and it still happens. Here are the classes in the test project

namespace Debug
{
    class Program
    {
        static void Main(string[] args)
        {
            TestClass test = System.Activator.CreateInstance<TestClass>();
        }
    }

    class TestClass
    { 
        internal TestClass() { }
    }
}

If I make the constructor public, the error doesn't occur, but why is that since Main should have access to it? What possible alternative could there be? I really can't just make the constructor public in the real project.

Another thing I tried was to move TestClass to the System namespace where Activator is located in case it's the CreateInstance method itself that doesn't have access to the constructor but the exception still gets thrown.

By Default Activator.CreateInstance only works with public constructors

However there is an overload that allows it to look for non-public constructors

public static object? CreateInstance (Type type, bool nonPublic);

https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance?view=netcore-3.1#System_Activator_CreateInstance_System_Type_System_Boolean _

You either don't understand, or have a misconception of, how access modifiers work.

You declared TestClass to have a single constructor that is internal . internal means that only types in the same namespace have access to that constructor. Activator is in the System namespace, which is not the same namespace as your class. Therefore Activator cannot, by default, access TestClass 's constructor.

Trying to put TestClass in the System namespace won't work because that would create a potential security risk - in such cases, the runtime ignores the fact that the namespaces are the same. To put it another way: you cannot add classes into any of the BCL namespaces.

Activator does allow you to invoke non-public constructors via its object? CreateInstance(Type type, bool nonPublic) object? CreateInstance(Type type, bool nonPublic) overload, but I'd question why you feel the need to have a non-public constructor anyway. After all, nothing is preventing other code from using that same overload to invoke your non-public constructor...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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