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

#c#

#c#

Вопрос:

У меня есть такой класс:

 public ClassA<T> where T : class{
       ...
}
  

Теперь мне нужно создать объект ClassA в конструкторе ClassB:

 public ClassB{
   public ClassA<?> objA;
   public ClassB(string TypeInfo){
       objA = new ClassA<?>(); // Suppose TypeInfo = 'ClassC', and the '?'
                               // Should be derived from TypeInfo
   }
   ...
}
  

Я не знаю, чем заменить ‘?’, поскольку тип может быть известен только во время выполнения… есть идеи?

Комментарии:

1. Примечание: я думаю ClassA , нужно объявить where T : class, new() , хотите ли вы использовать конструктор по умолчанию. Кроме того, @ArturMustafin ошибается.

2. Я хочу, чтобы ‘TypeInfo’ был строковым представлением типа объекта.

3. Я прав, потому что нет причин использовать generics для типов, неизвестных во время компиляции, потому что generics используется только для ИЗВЕСТНЫХ типов, что означает, что вы всегда можете произвести замену универсального параметра типом. Единственным подходящим типом в этой ситуации является object type

4. Единственный способ использовать тип, неизвестный во время компиляции, — это разрешить тип во время выполнения, создать ClassB универсальный и использовать ILGeberator() для универсального ClassB для создания экземпляра создания универсального ClassA типа во время выполнения

Ответ №1:

Наиболее близким к определению и созданию универсального типа во время выполнения, которое вы, вероятно, получите (используя строку, представляющую имя типа), является создание его экземпляра следующим образом.

 public class ClassB
{
    public ClassB(string typeInfo)
    {
        var typeOfT = Type.GetType(typeInfo);
        var type = typeof(ClassA<>).MakeGenericType(typeOfT);
        var instance = Activator.CreateInstance(type);
    }
}
  

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

 public dynamic objA;
  

Кроме того, строка, представляющая тип, должна быть достаточно квалифицирована, чтобы ее можно было найти без двусмысленности с помощью Type.GetType() . Например, SomeNamespace.ClassC вместо ClassC .

Комментарии:

1. Хороший код. Хотя это не может решить проблему определения класса, создание универсального типа — отличный трюк.

Ответ №2:

используйте object o = Activator.CreateInstance(constructed);

это пришло из MSDN http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx

Редактировать

мы используем его в методах расширения, таких как;

 public static object DefaultValue(this Type targetType) { return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; }
  

Заставить его работать с дженериками не составит большого труда

Комментарии:

1. Вы попадете в мою душу из-за типа использования object

Ответ №3:

Поскольку objA является частью определения ClassB, ClassB должен иметь параметр типа, если ClassA имеет параметр типа, т. е.

 public ClassB<T>
{
   public ClassA<T> objA
   ...
}
  

Если тип objA неизвестен во время компиляции, он должен быть типа Object или не общего базового или интерфейса. Середины нет.

Комментарии:

1. Цель состоит в том, чтобы использовать ‘TypeInfo’ в качестве источника информации о типе.

2. @baboonWorksFine — конечно, можно создавать определения типов динамически — вот как работает компилятор C #! Но вы пытаетесь выйти за пределы синтаксиса определения класса C #

Ответ №4:

Нет причин использовать generics для типов, неизвестных во время компиляции, потому что generics используется только для ИЗВЕСТНЫХ типов, что означает, что вы всегда можете произвести замену универсального параметра типом.

Единственным подходящим типом в рассматриваемой ситуации является object type, который является базовым классом для всех типов объектов и всегда известен компилятору.

 public ClassB{ 
   public ClassA<object> objA; 
   public ClassB(string TypeInfo){ 
       objA = new ClassA<object>();
   } 
   ... 
} 
  

О вашем вопросе…

Единственный способ использовать тип, неизвестный во время компиляции, — это разрешить тип во время выполнения, сделать класс B универсальным и использовать ILGenerator() для универсального класса A для создания экземпляра построения этого класса во время выполнения.

 public ClassB<T>{ 
   public ClassA<T> objA; 
   public ClassB(){ 
       objA = new ClassA<T>();
   } 
   ... 
} 
  

Комментарии:

1. Разве наличие ClassA, относящегося к типу object, не помешает цели использования дженериков?

2. Сам вопрос некорректен. Нет причин использовать общие типы для типов, которые повторно используются во время выполнения

3. Теперь, когда вы действительно объяснили свой ответ, я удалил мой downvote. Другие не всегда поймут вашу точку зрения, если вы предоставите только код.

4. @Artur — Ну, да. Сам вопрос не имел для меня особого смысла, но я подумал, что, возможно, был какой-то нюанс, о котором OP знал (или был ограничен), о котором я не знал.