2008-09-15 22 views
11

Estoy programando WCF usando ChannelFactory que espera un tipo para llamar al método CreateChannel. Por ejemplo:Dinámicamente Crear un tipo genérico para la plantilla

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

En mi caso, estoy haciendo enrutamiento, así que no sé qué tipo utilizará mi fábrica de canales. Puedo analizar un encabezado de mensaje para determinar el tipo pero choco contra una pared de ladrillo porque incluso si tengo una instancia de Tipo I no puedo pasar eso donde ChannelFactory espera un tipo genérico.

Otra forma de replantear este problema en términos muy simples sería que yo estoy tratando de hacer algo como esto:

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? 

¿Hay un acercamiento a esto puedo aprovechar en C#?

+0

posible duplicado de [Paso Una System.Type crea la instancia como un parámetro de tipo de una clase genérica] (http://stackoverflow.com/questions/266115/pass-an-instantiated-system -type-as-a-type-parameter-for-a-generic-class) – nawfal

Respuesta

22

Lo que se busca es 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); 

Así que lo que está haciendo es conseguir que el tipo de definición de la clase genérica "plantilla", entonces la construcción de una especialización del tipo que utiliza los tipos de tiempo de ejecución de conducción .

4

Aquí hay una pregunta: ¿Tiene Realmente necesita crear un canal con el tipo de contrato exacto en su caso específico?

Dado que está haciendo enrutamiento, hay una gran posibilidad de que simplemente pueda tratar con las formas genéricas de los canales. Por ejemplo, si usted está trazando un solo sentido mensaje, entonces se podría crear un canal para enviar el mensaje a cabo de esta manera:

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

Si usted necesita para enviar a un servicio de dos vías, sólo tiene que utilizar IRequestChannel en su lugar.

Si está haciendo enrutamiento, es, en general, mucho más fácil tratar con formas de canal genéricas (con un contrato genérico de servicio global para el exterior) y simplemente asegúrese de que el mensaje que está enviando tiene todos los encabezados y propiedades correctos.

+1

Tuve un dilema que marcó la "respuesta" a mi pregunta. En términos de usar WCF, pude utilizar esta técnica que mencionas y funciona como un amuleto (¡gracias!). Elegí lo anterior ya que técnicamente responde la pregunta que hice (incluso si esta es una mejor manera). – t3rse

8

Debería ver esta publicación de Ayende: WCF, Mocking and IoC: Oh MY!. En algún lugar cerca de la parte inferior es un método llamado GetCreationDelegate que debería ayudar. Básicamente hace esto:

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