Я программирую 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#?





Что вы ищете, так это 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.
Вот вопрос: нужно ли вам В самом деле создавать канал с точным типом контракта в вашем конкретном случае?
Поскольку вы выполняете маршрутизацию, есть очень большая вероятность, что вы сможете просто иметь дело с общими формами каналов. Например, если вы маршрутизируете одностороннее сообщение, вы можете создать канал для отправки сообщения следующим образом:
ChannelFactory<IOutputChannel> factory = new ChannelFactory<IOutputChannel>(binding, endpoint);
IOutputChannel channel = factory.CreateChannel();
...
channel.SendMessage(myRawMessage);
Если вам нужно отправить в двустороннюю службу, просто используйте вместо этого IRequestChannel.
Если вы выполняете маршрутизацию, то, как правило, намного проще иметь дело с общими формами каналов (с общим универсальным сервисным контрактом извне) и просто убедиться, что отправляемое вами сообщение правильно заголовки и свойства.
У меня возникла дилемма, отмечая «ответ» на мой вопрос. Что касается использования WCF, я смог использовать эту технику, о которой вы упомянули, и она отлично работает (спасибо!). Я выбрал вариант выше, поскольку он технически отвечает на заданный мною вопрос (даже если это лучший способ).
Вы должны посмотреть этот пост от Айенде: 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]);
возможный дубликат Передайте созданный экземпляр System.Type в качестве параметра типа для универсального класса