Pergunta

Estou programando o WCF usando o ChannelFactory que espera um tipo para chamar o método CreateChannel.Por exemplo:

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

No meu caso, estou fazendo roteamento, então não sei que tipo minha fábrica de canais usará.Posso analisar um cabeçalho de mensagem para determinar o tipo, mas bati em uma parede de tijolos porque, mesmo que eu tenha uma instância de Type, não posso passar onde ChannelFactory espera um tipo genérico.

Outra maneira de reafirmar esse problema em termos muito simples seria tentar fazer algo assim:

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?

Existe uma abordagem para isso que eu possa aproveitar em C#?

Foi útil?

Solução

O que você está procurando é 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);

Então, o que você está fazendo é obter a definição de tipo da classe "modelo" genérica e, em seguida, construir uma especialização do tipo usando seus tipos de condução em tempo de execução.

Outras dicas

Você deveria dar uma olhada nesta postagem de Ayende: WCF, simulação e IoC:Oh meu Deus!.Em algum lugar próximo ao final está um método chamado GetCreationDelegate que deve ajudar.Basicamente faz isso:

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]);

Aqui está uma pergunta:Você realmente precisa criar um canal com o tipo de contrato exato do seu caso específico?

Como você está fazendo roteamento, há uma boa chance de você simplesmente lidar com os formatos genéricos do canal.Por exemplo, se você estiver encaminhando uma mensagem unidirecional, poderá criar um canal para enviar a mensagem assim:

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

Se você precisasse enviar para um serviço bidirecional, basta usar IRequestChannel.

Se você estiver fazendo roteamento, é, em geral, muito mais fácil apenas lidar com formatos de canal genéricos (com um contrato de serviço genérico genérico para o exterior) e apenas certificar-se de que a mensagem que você está enviando está correta. cabeçalhos e propriedades.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top