Instantiating Internal class with private constructor

前端 未结 5 967
挽巷
挽巷 2020-11-30 08:25

I am trying to use reflection to create instance of a class. But it is sealed internal and has private constructor. I wonder how can i initiaise it and as its part of framew

相关标签:
5条回答
  • 2020-11-30 09:06

    First of all, the very fact that it is internal means you're not supposed to be doing what you want to do.

    You should seriously try to find an alternate route to what you want to accomplish.

    Unfortunately, you don't tell us what you want to accomplish, only the next step you think you want to do, so that's what I can help you with.

    This code will work, and accesses the public static method:

    Type t = typeof(SomeOtherTypeInSameAssembly)
        .Assembly.GetType("ClassLibrary1.ABC");
    MethodInfo method = t.GetMethod("Create",
        BindingFlags.Public | BindingFlags.Static, null,
        new Type[] { typeof(String) },
        new ParameterModifier[0]);
    Object o = method.Invoke(null, new Object[] { "test" });
    

    Note that this relies on having access to another type in the same assembly, that is public. If you don't have that, you need to get hold of the Assembly object that contains the type.

    0 讨论(0)
  • 2020-11-30 09:07

    You can't instantiate classes with private constructors unless it's a nested class.

    http://msdn.microsoft.com/en-us/library/kcfb85a6%28VS.71%29.aspx

    0 讨论(0)
  • 2020-11-30 09:10

    If it's internal to an assembly that is not yours and the constructor is marked as private, the author of the assembly is trying very hard to keep you from creating the object.

    The below is really evil as you're relying on non-public classes and methods which could change on you without advance notice.

    Added: System.ServiceModel.Channels.SelfSignedCertificate is the internal class I am trying to use

    Do not do this. The framework could change under you in the blink of an eye ruining your code and all of your hard work.

    That said, you could do this:

    MethodInfo method = Type.GetType(assemblyQualifiedName).GetMethod("Create");
    ABC o = (ABC)method.Invoke(null, new[] { "test" });
    

    This invokes the static method Create. Another option is

    MethodInfo method = Type.GetType(assemblyQualifiedName).GetConstructor(
                            BindingFlags.NonPublic | BindingFlags.Instance,
                            null,
                            new[] { typeof(string) },
                            null
                        );
    ABC o = (ABC)method.Invoke(new[] { "test" });
    

    which uses reflection to load the constructor that accepts a string as a parameter.

    An easy way to get the assembly-qualified name is

    string name = typeof(somePublicType).Assembly.GetType("Namespace.ABC");
    

    where somePublicType is a type that is public and in the same assembly as ABC.

    0 讨论(0)
  • 2020-11-30 09:16

    Use the Activator class to instantiate it

    Activator.CreateInstance(myType, true);
    
    0 讨论(0)
  • 2020-11-30 09:26

    EDIT: I hadn't noticed that you mentioned that the type you're trying to initialize is part of the .NET framework. I thought it was one of your own types, just referenced from elsewhere.

    I would strongly urge you not to attempt this. Microsoft are perfectly at liberty to change or remove internal classes between framework releases - your code will be incredibly brittle if you rely on implementation details like this.

    Change your design to avoid needing to do this.


    Original answer:

    Yes, you'd have to use reflection - like this:

    using System;
    using System.Reflection;
    
    internal sealed class ABC
    {
        private ABC(string password)
        {
            Console.WriteLine("Constructor called");
        }
    }
    
    public class Test
    {
        static void Main()
        {
            ConstructorInfo ctor = typeof(ABC).GetConstructors
                (BindingFlags.Instance | BindingFlags.NonPublic)[0];
    
            ABC abc = (ABC) ctor.Invoke(new object[] { "test" });
        }
    }
    

    Note that violating access modifiers in this way requires the ReflectionPermissionFlag.MemberAccess permission. If you know there will be a static method called Create, you'd be better off invoking that via reflection:

    using System;
    using System.Reflection;
    
    internal sealed class ABC
    {
        private ABC(string password)
        {
            Console.WriteLine("Constructor called");
        }
    
        public static ABC Create(string password)
        {
            return new ABC(password);
        }
    }
    
    public class Test
    {
        static void Main()
        {
            MethodInfo method = typeof(ABC).GetMethod("Create",
                BindingFlags.Static | BindingFlags.Public);
    
            ABC abc = (ABC) method.Invoke(null, new object[]{"test"});
        }
    }
    
    0 讨论(0)
提交回复
热议问题