Как создать объект с закрытым конструктором в C #? - PullRequest
30 голосов
/ 02 апреля 2009

Я точно помню, что где-то видел пример того, как сделать это с помощью отражения или чего-то еще. Это было что-то, что имело отношение к SqlParameterCollection, который не создавался пользователем (если я не ошибаюсь). К сожалению не могу найти его больше.

Может кто-нибудь поделиться этим трюком здесь? Не то чтобы я считаю это правильным подходом к разработке, я просто очень заинтересован в возможности сделать это.

Ответы [ 5 ]

57 голосов
/ 02 апреля 2009

Для этого можно использовать одну из перегрузок Activator.CreateInstance : Activator.CreateInstance(Type type, bool nonPublic)

Используйте true для аргумента nonPublic. Потому что true соответствует общедоступному или непубличному конструктору по умолчанию; false соответствует только общедоступному конструктору по умолчанию.

Например:

    class Program
    {
        public static void Main(string[] args)
        {
            Type type=typeof(Foo);
            Foo f=(Foo)Activator.CreateInstance(type,true);
        }       
    }

    class Foo
    {
        private Foo()
        {
        }
    }
40 голосов
/ 02 апреля 2009
// the types of the constructor parameters, in order
// use an empty Type[] array if the constructor takes no parameters
Type[] paramTypes = new Type[] { typeof(string), typeof(int) };

// the values of the constructor parameters, in order
// use an empty object[] array if the constructor takes no parameters
object[] paramValues = new object[] { "test", 42 };

TheTypeYouWantToInstantiate instance =
    Construct<TheTypeYouWantToInstantiate>(paramTypes, paramValues);

// ...

public static T Construct<T>(Type[] paramTypes, object[] paramValues)
{
    Type t = typeof(T);

    ConstructorInfo ci = t.GetConstructor(
        BindingFlags.Instance | BindingFlags.NonPublic,
        null, paramTypes, null);

    return (T)ci.Invoke(paramValues);
}
4 голосов
/ 02 апреля 2009

Это вопрос, который вы задавали? Activator.CreateInstance с закрытым закрытым классом

2 голосов
/ 02 апреля 2009

Если класс не один из ваших, то похоже, что API был специально написан для предотвращения этого, а это значит, что, возможно, ваш подход не тот, который предполагали авторы API. Посмотрите документы и посмотрите, есть ли рекомендуемый подход к использованию этого класса.

Если у вас есть контроль над классом и вы хотите реализовать этот шаблон, то он обычно реализуется с помощью статического метода в классе. Это ключевая концепция, которая также составляет шаблон Singleton.

Например:

public PrivateCtorClass
{
    private PrivateCtorClass()
    {
    }

    public static PrivateCtorClass Create()
    {
        return new PrivateCtorClass();
    }
}

public SomeOtherClass
{
    public void SomeMethod()
    {
        var privateCtorClass = PrivateCtorClass.Create();
    }
}

Хороший пример - материал SqlCommandParameter. Они ожидают, что вы создадите параметры, вызывая такие вещи:

var command = IDbConnnection.CreateCommand(...);
command.Parameters.Add(command.CreateParameter(...));

Мой пример не очень хороший код, потому что он не демонстрирует установку свойств параметров команды или повторное использование параметров / команд, но вы поняли идею.

1 голос
/ 22 августа 2016

Это также поможет, если ваш Type равен private или internal:

 public static object CreatePrivateClassInstance(string typeName, object[] parameters)
    {
        Type type = AppDomain.CurrentDomain.GetAssemblies().
                 SelectMany(assembly => assembly.GetTypes()).FirstOrDefault(t => t.Name == typeName);
        return type.GetConstructors()[0].Invoke(parameters);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...