2016-10-06 3 views
1

Я хотел бы создать экземпляр нового объекта, где тип и общий тип определяются как переменные. Окончательный результат может выглядеть newListOfObjects созданного вручную здесь:Мгновенное создание общего типа из переменной

var newListOfObjects = new List<TabViewModel>(); 

Где TabViewModel является следующим объектом:

public class TabViewModel 
{ 
    public string Title { get; set; } 
    public int TabOrder { get; set; } 
} 

Проблема возникает при попытке создать экземпляр нового объекта, используя только переменные. У нас есть одна универсальная переменная типа genericType, которая представляет собой интерфейс и один список аргументов типа, listOfTypeArgs. В приведенном выше примере общий тип будет IList, а аргументами будет TabViewModel. Это будет выглядеть следующим образом (примечания, некоторые коды psudo для облегчения понимания):

Type genericType = IList'1; 
Type[] listOfTypeArgs = TabViewModel; 
var newObject = Activator.CreateInstance(genericType.MakeGenericType(listOfTypeArgs)); 

Тогда очевидно, что я получаю ошибку «System.MissingMethodException» с запиской, что я не могу создать экземпляр переменная от интерфейса.

Как преобразовать интерфейс в его представительный, чтобы я мог создать экземпляр нового объекта?

ПРИМЕЧАНИЕ: Я не могу изменить тип genericType = IList'1; nor Тип [] listOfTypeArgs = TabViewModel;

+2

Этот тип 'GenericType = IList'1;' 'и этот тип [] listOfTypeArgs = TabViewModel;' не является допустимым в C# синтаксис. Отправьте фактический код! – user3185569

+0

Действительный код для получения типа IList и TabViewModel в этом случае не имеет значения. –

+0

Вы можете прочитать http://stackoverflow.com/help/mcve перед публикацией, если вы решите проигнорировать запрос user3185569. – Aziuth

ответ

0

Ошибка самодокументирующимся, вам нужны конкретные типы для создания экземпляра. Вместо IList (который не имеет реализации и просто контракт), вы должны использовать реализацию IList:

Type genericType = typeof(List<>); 
Type[] listOfTypeArgs = new[] { typeof(TabViewModel) }; 
var newObject = Activator.CreateInstance(genericType.MakeGenericType(listOfTypeArgs)); 

Edit:

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

Type genericType = typeof(List<>); 
Type concreteType = AppDomain.CurrentDomain.GetAssemblies() 
          .SelectMany(s => s.GetTypes()) 
          .Where(p => genericType.IsAssignableFrom(p)).FirstOrDefault(); 

Type[] listOfTypeArgs = new[] { typeof(TabViewModel) }; 
var newObject = Activator.CreateInstance(concreteType.MakeGenericType(listOfTypeArgs)); 
+0

Прекрасный ответ, но, к сожалению, я не могу изменить переменную genericType. Я получаю только интерфейс, и это моя проблема. –

+0

@ViktorLeandersson. Затем вам нужно использовать отражение, чтобы найти реализацию этого интерфейса. Проверьте отредактированный ответ – user3185569

0

Вы должны использовать List<> типа как так:

var genericType = typeof(List<>); 
var boundType = genericType.MakeGenericType(typeof(TabViewModel)); 
var instance = Activator.CreateInstance(boundType); 
+0

Прекрасный ответ, но, к сожалению, я не могу изменить переменную genericType. Я получаю только интерфейс, и это моя проблема. –

+0

@ViktorLeandersson. Затем вы можете создать карту, которая отображает все ваши возможные интерфейсы для конкретных реализаций, например. 'IList <>' сопоставляется с 'List <>' – Nico

Смежные вопросы