#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
type4. Единственный способ использовать тип, неизвестный во время компиляции, — это разрешить тип во время выполнения, создать
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 знал (или был ограничен), о котором я не знал.