Подтвердить что ты не робот

Как создать экземпляр объекта с помощью частного конструктора в С#?

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

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

4b9b3361

Ответ 1

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

Ответ 2

Вы можете использовать одну из перегрузок 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()
        {
        }
    }

Ответ 4

Если класс не принадлежит вам, то это звучит так, будто 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(...));

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

Ответ 5

Это также поможет, если ваш 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);
    }