Динамическое создание универсального типа для шаблона

Я программирую WCF с помощью ChannelFactory, который ожидает тип для вызова метода CreateChannel. Например:

IProxy proxy = ChannelFactory<IProxy>.CreateChannel(...);

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

Другой способ переформулировать эту проблему очень простым языком - это попытаться сделать что-то вроде этого:

string listtype = Console.ReadLine(); // say "System.Int32"
Type t = Type.GetType( listtype);
List<t> myIntegers = new List<>(); // does not compile, expects a "type"
List<typeof(t)> myIntegers = new List<typeof(t)>(); // interesting - type must resolve at compile time?

Есть ли подход к этому, который я могу использовать в C#?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
14
1
19 662
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Что вы ищете, так это MakeGenericType

string elementTypeName = Console.ReadLine();
Type elementType = Type.GetType(elementTypeName);
Type[] types = new Type[] { elementType };

Type listType = typeof(List<>);
Type genericType = listType.MakeGenericType(types);
IProxy  proxy = (IProxy)Activator.CreateInstance(genericType);

Итак, что вы делаете, это получаете определение типа универсального «шаблонного» класса, а затем строите специализацию этого типа с использованием ваших управляющих во время выполнения типов.

На самом деле мы можем просто назвать listType.MakeGenericType(elementType) - это аргумент params.

rsenna 08.04.2020 22:28

Вот вопрос: нужно ли вам В самом деле создавать канал с точным типом контракта в вашем конкретном случае?

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

ChannelFactory<IOutputChannel> factory = new ChannelFactory<IOutputChannel>(binding, endpoint);
IOutputChannel channel = factory.CreateChannel();
...
channel.SendMessage(myRawMessage);

Если вам нужно отправить в двустороннюю службу, просто используйте вместо этого IRequestChannel.

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

У меня возникла дилемма, отмечая «ответ» на мой вопрос. Что касается использования WCF, я смог использовать эту технику, о которой вы упомянули, и она отлично работает (спасибо!). Я выбрал вариант выше, поскольку он технически отвечает на заданный мною вопрос (даже если это лучший способ).

t3rse 16.09.2008 22:49

Вы должны посмотреть этот пост от Айенде: WCF, Mocking и IoC: О МОЙ!. Где-то внизу есть метод GetCreationDelegate, который должен помочь. В основном он делает это:

string typeName = ...;
Type proxyType = Type.GetType(typeName);

Type type = typeof (ChannelFactory<>).MakeGenericType(proxyType);

object target = Activator.CreateInstance(type);

MethodInfo methodInfo = type.GetMethod("CreateChannel", new Type[] {});

return methodInfo.Invoke(target, new object[0]);

Другие вопросы по теме