Как создать экземпляр объекта по его типу (Type) в C#?
Использование Activator.CreateInstance
Для создания объекта по типу в C# используется класс Activator из пространства имён System. Это самый простой и распространённый способ. Вот как это работает:
using System;
using System.Text;
Type type = typeof(StringBuilder);
object instance = Activator.CreateInstance(type);
Console.WriteLine(instance.GetType()); // Выведет: System.Text.StringBuilder
Activator.CreateInstance вызывает конструктор без параметров. Если такого конструктора нет, будет выброшено исключение MissingMethodException.
Создание объекта с параметрами конструктора
Если конструктор принимает аргументы, передайте их в виде массива объектов:
Type type = typeof(StringBuilder);
object[] args = new object[] { "Hello, World!" };
object instance = Activator.CreateInstance(type, args);
Console.WriteLine(instance.ToString()); // Выведет: Hello, World!
Проверка наличия конструктора без параметров
Чтобы избежать ошибок, можно проверить существование конструктора:
Type type = typeof(MyClass);
ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
if (ctor != null)
{
object instance = Activator.CreateInstance(type);
}
else
{
Console.WriteLine("Нет конструктора без параметров");
}
Производительность и альтернативы
Activator.CreateInstance использует рефлексию, что медленнее прямого вызова new. Для частого создания объектов рассмотрите:
- Expression Trees — компиляция делегата для создания объекта.
- Фабричный метод — если тип известен заранее.
- FormatterServices.GetUninitializedObject — для создания объекта без вызова конструктора (опасно, только для сериализации).
Пример с обобщённым методом
Часто удобно создать вспомогательный метод:
public T CreateInstance<T>(params object[] args)
{
return (T)Activator.CreateInstance(typeof(T), args);
}
// Использование:
StringBuilder sb = CreateInstance<StringBuilder>("Hello");
Важные замечания
- Создаваемый тип должен быть публичным и иметь доступный конструктор.
- Для абстрактных классов или интерфейсов будет ошибка.
- Для generic-типов сначала нужно создать конкретный тип через
MakeGenericType.
В большинстве случаев Activator.CreateInstance — это то, что вам нужно. Он простой, надёжный и покрывает 95% сценариев динамического создания объектов.
Использование ConstructorInfo и Invoke
Если вам нужен более тонкий контроль над созданием объекта (например, выбор конкретного конструктора или работа с non-public конструкторами), используйте ConstructorInfo.Invoke:
Type type = typeof(MyClass);
// Получаем конструктор с одним параметром типа string
ConstructorInfo ctor = type.GetConstructor(new[] { typeof(string) });
if (ctor != null)
{
object instance = ctor.Invoke(new object[] { "test" });
}
Этот метод даёт доступ ко всем конструкторам, включая private (через BindingFlags):
ConstructorInfo ctor = type.GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
null, Type.EmptyTypes, null);
object instance = ctor.Invoke(null);
Когда это полезно?
- Если нужно вызвать private конструктор (например, для паттерна Singleton).
- Если в классе несколько конструкторов и нужно явно указать, какой использовать.
- Если требуется кэширование
ConstructorInfoдля повышения производительности.
Однако для простых случаев Activator.CreateInstance предпочтительнее — он короче и понятнее.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги