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

StackOverflow https://stackoverflow.com/questions/67370

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

В моем случае я выполняю маршрутизацию, поэтому не знаю, какой тип будет использовать моя фабрика каналов.Я могу проанализировать заголовок сообщения, чтобы определить тип, но здесь я упираюсь в кирпичную стену, потому что даже если у меня есть экземпляр Type, я не могу передать его там, где 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);

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

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

Вы должны посмотреть этот пост от Ayende: 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]);

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top