Domanda

Sto programmando WCF utilizzando ChannelFactory che prevede un tipo per chiamare il metodo CreateChannel.Per esempio:

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

Nel mio caso sto eseguendo il routing, quindi non so quale tipo utilizzerà la mia channel factory.Posso analizzare l'intestazione di un messaggio per determinare il tipo, ma mi trovo di fronte a un muro di mattoni perché anche se ho un'istanza di Type non posso passarla dove ChannelFactory si aspetta un tipo generico.

Un altro modo per riaffermare questo problema in termini molto semplici sarebbe che sto tentando di fare qualcosa del genere:

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?

Esiste un approccio a questo che posso sfruttare in C#?

È stato utile?

Soluzione

Quello che stai cercando è 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);

Quindi quello che stai facendo è ottenere la definizione del tipo della classe "modello" generica, quindi creare una specializzazione del tipo utilizzando i tipi di guida in runtime.

Altri suggerimenti

Dovresti guardare questo post di Ayende: WCF, Mocking e IoC:Oh mio!.Da qualche parte vicino al fondo c'è un metodo chiamato GetCreationDelegate che dovrebbe aiutare.Fondamentalmente fa questo:

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

Ecco una domanda:Fai Veramente devi creare un canale con la tipologia contrattuale esatta nel tuo caso specifico?

Dato che stai eseguendo il routing, ci sono ottime possibilità che tu possa semplicemente gestire le forme generiche dei canali.Ad esempio, se stai indirizzando un messaggio unidirezionale, potresti creare un canale per inviare il messaggio in questo modo:

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

Se hai bisogno di inviare a un servizio bidirezionale, usa semplicemente IRequestChannel.

Se stai eseguendo il routing, in generale è molto più semplice gestire solo forme di canale generiche (con un contratto di servizio generico catch-all verso l'esterno) e assicurarti semplicemente che il messaggio che stai inviando abbia tutti i diritti intestazioni e proprietà.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top