Почему мне нужно использовать рефлексию для создания экземпляра обобщенного типа объекта типа? - PullRequest
3 голосов
/ 11 октября 2011

У меня есть список объектов Type, соответствующих моим сущностям, и я хочу использовать эти типы для создания экземпляров соответствующих общих связывателей ... ну, позвольте мне показать это:

foreach (Type entitytype in Core.EntityList.Entities)
        {   
Type generictype = typeof(CustomBinders.Binder<>);
Type actualtype = generictype.MakeGenericType(new Type[] { entitytype });
IModelBinder custombinder = (IModelBinder)Activator.CreateInstance(actualtype);
.....................

Вышеуказанное работает: каждый созданный связыватель затем добавляется в словарь связывателей, который будет использоваться приложением mvc. Но почему я вынужден использовать отражение? Я считаю, что это включает в себя время выполнения против времени компиляции, что я не понимаю. Список типов есть во время компиляции.

Если кто-то может предложить другой шаблон и / или объяснить мне эти вещи, то это было бы хорошо. Кажется, что, учитывая объект типа, я должен быть в состоянии создать экземпляр объекта, просто используя новый. Что динамического в том, что я пытаюсь сделать?

Ответы [ 2 ]

1 голос
/ 11 октября 2011

Скажем, вы хотите построить стол. Вы уже знаете размеры заранее, какой материал использовать, сколько это будет стоить и так далее, поэтому вы просто создаете таблицу.

var table = new Table();

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

foreach(Type plan in planBox) Activator.CreateInstance(plan);

Разница в том, что тип - это часть метаданных, которые у вас есть во время выполнения о данном объекте (так сказать, планах). Если бы вы знали тип во время компиляции, вы бы поместили его непосредственно в свой код, но вы не представляете, что произойдет через ваш блок Core.EntityList.Entities, и поэтому вы должны использовать отражение, чтобы использовать эту информацию времени выполнения соответствующим образом.

Дело в том, что если вы используете информацию времени выполнения, вы должны использовать возможности времени выполнения. Если все типы известны во время компиляции, не используйте объекты Type.

1 голос
/ 11 октября 2011

Если вы хотите использовать new, вы можете подумать о том, чтобы сделать что-то вроде этого:

foreach (Type entityType in Core.EntityList.Entities)
{   
    IModelBinder obj = new CustomBinders.Binder<entityType>()
    // Then add it to the dictionary
}

Однако в C # это недопустимо - оно выдаст ошибку «Ожидается тип или имя пространства имен». Обобщениям нужен параметр типа, определенный во время компиляции, чтобы он мог обеспечить все проверки во время компиляции. Таким образом, вам нужно использовать отражение, чтобы сделать это динамически.

Что касается того, что на самом деле делает отражение в этом случае:

Type generictype = typeof(CustomBinders.Binder<>);

Получает ссылку на универсальный тип " unbound " (т. Е. Ему еще не присвоен параметр типа).

Type actualtype = generictype.MakeGenericType(new Type[] { entitytype });

Это дает вам ссылку на тип " построенный ", то есть тип с типом сущности в качестве параметра типа (то есть CustomBinders.Binder<entityType>)

IModelBinder custombinder = (IModelBinder)Activator.CreateInstance(actualtype);

Это создает объект для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...