2010-08-02 11 views
3

Je travaille sur une interface client (Silverlight) à une collection de webmethod. Et j'essaie d'éviter d'écrire du code personnalisé pour chaque méthode web. J'ai donc créé un ServiceCall<TResult> pour gérer chaque appel, TResult spécifie le type de retour du service (j'utilise XmlSerializer pour créer l'instance retournée). La classe client expose une fonction correspondant à chaque méthode web, et toute cette fonction doit créer une nouvelle instance de ServiceCall<TResult>, avec le TResult spécifié comme type de retour attendu de la méthode. Et cela fonctionne très bien. J'utilise également Ninject (injecteur de dépendances) pour essayer de tout garder indépendant. Ninject supporte les génériques ouverts, ce qui fonctionne bien avec mon ServiceCall<TResult>.Comment fabriquez-vous une usine générique générique?

Mais cela signifie aussi que j'injecte une référence au conteneur Ninject. Ce qui cache la dépendance sur ServiceCall<TResult> étant lié au conteneur. Donc, je voudrais plutôt injecter une usine pour créer mes instances ServiceCall<TResult>. Ce qui n'est pas délicat, mais j'aimerais en faire une usine générique générique. Sens Je voudrais avoir quelque chose comme Factory<T<>> qui aurait une méthode public T<TU> Createinstance<TU>().

Mais je n'ai aucune idée comment je pourrais créer une classe générique avec un paramètre de type qui est lui-même un générique ouvert.

L'événement est-il possible dans .Net? - Ou dois-je créer un ServiceCallFactory spécifique?

Edit: J'utilise des interfaces pour les dépendances, mais il n'y a pas besoin de les mélanger dans la question ici, donc je que modifié sur la question.

En responce à Timwi: La façon courante d'utiliser l'injection de dépendance (DI) est de lier une interface à votre mise en œuvre, seul le conteneur connaît ces liaisons. Vous codez ensuite contre les interfaces à la place. Cela apporte une tonne d'avantages. Plus que je ne peux mentionner ici.
De toute façon, il exclut également les classes statiques (puisque ce serait une dépendance sur une classe spécifique). Au lieu de cela, je vais demander au conteneur (Ninject dans ce cas) de toujours me donner la même instance pour l'interface d'usine, dans un comportement similaire à celui d'un singleton.
Ceci exclut l'option public static class Factory<T>, car elle est statique, et si elle n'est pas statique, j'aurais besoin maintenant de tous les types de T que j'utiliserai, ce qui va à l'encontre du but d'avoir une classe générique.
La suggestion d'avoir une classe non générique avec une méthode "totalement générique" (comme je passe dans ServiceCall<MyResult> au lieu de seulement MyResult), est ce que je fais maintenant plus ou moins (moins la partie statique). Le conteneur Ninject a une méthode Get qui fonctionne comme votre deuxième suggestion.
Le problème avec ceci est deux parties; Premièrement, cela rend mon code directement dépendant d'un conteneur (Ninject), mais ce n'est pas vraiment un gros problème pour moi. Ce qui m'ennuie, c'est que si vous me regardez de l'extérieur, vous ne verrez qu'une dépendance à Ninject. Vous ne saurez pas jusqu'à ce que vous exécutez essayer de faire un appel que le client a besoin d'une implémentation de ServiceCall enregistré avec Ninject pour fonctionner.
Mais si le constructeur du client prenait un paramètre de type Factory>, il serait beaucoup plus clair.

En tout cas je pense que ce serait un problème commun, donc soit une solution commune, ou ce n'est pas un problème commun et j'essaie de faire quelque chose de stupide;) Je ne suis toujours pas dans l'injection de dépendance , ce qui peut très bien être le cas.

+0

Est « IServiceCall » un exemple d'un appel de service spécifique (comme « foo »), ou est-ce une interface réelle pour cette API vous construisez? –

+0

C'est une interface. Ma mise en œuvre spécifique est ServiceCall. Je l'utilise pour être dépendant d'une interface plutôt que d'une implémentation spécifique. Mais cela ne pose aucun problème à cette question. Je vais éditer le post. –

Répondre

4

Est-ce que vous cherchez: Generic Factory Pattern

namespace GenericFactoryPatternTestApp 
{ 
    public class Factory<T> 
    { 
     private readonly Dictionary< string, Type > _factoryDictionary = new Dictionary< string, Type >(); 

     public Factory() 
     {  
      Type[] types = Assembly.GetAssembly(typeof (T)).GetTypes(); 

      foreach (Type type in types) 
      { 
       if (!typeof (T).IsAssignableFrom(type) || type == typeof (T)) 
       { 
        // Incorrect type 
        continue; 
       } 

       // Add the type 
       _factoryDictionary.Add(type.Name, type); 
      } 
     } 

     public T Create<V>(params object[] args) 
     { 
      return (T) Activator.CreateInstance(_factoryDictionary[typeof (V).Name], args); 
     } 
    } 
} 
1

Donc, si je vous comprends bien, vous auriez une classe à la recherche un peu comme ceci:

public static class Factory<T<>> 
{ 
    public static T<TU> CreateInstance<TU>() { /* ... */ } 
} 

puis vous appelez comment? Comme ça?

var myServiceCall = Factory<ServiceCall<>>.CreateInstance<MyResult>(); 

Ce qui vous empêche de déclarer simplement l'usine comme ça ...

public static class Factory<T> 
{ 
    public static T CreateInstance() { /* ... */ } 
} 

... ou ... ce

public static class Factory 
{ 
    public static T CreateInstance<T>() { /* ... */ } 
} 

... puis générer votre instance comme ça?

var myServiceCall = Factory<ServiceCall<MyResult>>.CreateInstance(); 
var myServiceCall = Factory.CreateInstance<ServiceCall<MyResult>>(); 

Je suis désolé si je suis stupide, mais je serais probablement besoin de savoir comment fonctionne Ninject et comment il vous permet de passer dans une usine.

+0

Je vais laisser un commentaire dans la question puisque l'espace est un peu court ici. –