2011-06-22 3 views
1

J'essaie d'utiliser Unity avec mon service de données WCF (OData). J'ai le code qui ressemble à ceci: (., Soit le vrai PatientRepository ou un truquée que j'utilise pour le test)Unity et OData (services de données WCF)

public class PatientService : DataService<IPatientRepository> 

Je veux l'unité d'injecter l'objet correct pour IPatientRepository au moment de l'exécution

Je fait le:

IUnityContainer container = new UnityContainer(); 
container.RegisterType<IPatientRepository, MyEntities>(); 

Mais quand je cours, je reçois:

le serveur a rencontré un traitement d'erreur la demande. Le message d'exception est 'Impossible de créer le fournisseur de données. Tapez 'RepositoryInterfaces.IPatientRepository' pour la source de données dans 'PatientService.PatientService' est abstrait. '

Existe-t-il un moyen d'injecter cette dépendance? Ou dois-je mettre la vraie classe à cet endroit?

Répondre

0

WCF Data Services ne connaît pas votre conteneur et ne peut donc pas l'appeler pour connaître l'implémentation de l'interface que vous transmettez.

De même, votre conteneur peut effectuer une injection de constructeur mais ne peut pas spécifier dynamiquement le T dans DataService <T>. Pour autant que je sache, il n'y a aucun moyen d'utiliser DataService avec une interface, puis d'injecter une implémentation.

EDIT: Que faut travailler, comme Vitek a souligné dans les commentaires, est de simplement déclarer votre classe un DataSource <T> avec une interface, puis remplacer la méthode CreateDataSource(). Dans cette méthode, vous pouvez alors faire un appel ServiceLocator à la mise en œuvre de IYourInterface:

var myService = ServiceLocator.Get<IYourInterface>(); 

Bien sûr, exige que vous configurez votre conteneur pour l'emplacement de service.

Les modèles & Le groupe Practices a apparemment implémenté un adaptateur Unity pour le modèle Service Locator, voir http://commonservicelocator.codeplex.com/wikipage?title=Unity%20Adapter&referringTitle=Home&ProjectName=commonservicelocator. Pour plus d'informations sur le modèle Service Locator, voir http://msdn.microsoft.com/en-us/library/ff648968.aspx.

+0

Vous pouvez définir les DataService où T est une interface. Mais alors vous devez surcharger la méthode CreateDataSource et instancier la classe de contexte (qui implémente cette interface). Je ne sais pas si cela fonctionnera avec l'injection si. –

+0

@Vitek: Peut-être que si vous substituez CreateDataSource, puis utilisez ServiceLocator dans le remplacement? Cela pourrait fonctionner. –

+0

Essayez de ne pas utiliser ServiceLocator si vous pouvez l'éviter. C'est un anti-pattern tel que décrit dans cet article http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ par Mark Seemann, qui était le développeur original de la classe ServiceLocator pour Microsoft Patterns and Practices. Il est parti tout de suite pour de bonnes raisons. –

1

La classe ServiceLocator et le ServiceLocator (anti)pattern ne doivent pas être utilisés ici. Le code ci-dessous ressemble à un modèle de localisateur de service (anti), mais ce n'est pas tout à fait le cas.

La méthode CreateDataSource est le premier point du cycle de vie de la requête que j'ai trouvé pour composer votre graphe d'objet. Ici, il est utilisé comme racine de composition. Bootstrapper est une classe d'assistance qui appelle la configuration Unity, qu'elle soit en cours de chargement à partir de XML ou de code.

public class PatientService : DataService<IPatientRepository> 
{ 
    public static void InitializeService(DataServiceConfiguration config) 
    { 
     // TODO: set rules to indicate which entity sets and service 
      operations are visible, updatable, etc. 
      ... 
    } 

    [WebGet] 
    public IQueryable<Patient> Patients() 
    { 
     return from p in CurrentDataSource.Patients select p; 
    } 

    protected override IPatientRepository CreateDataSource() 
    { 
     IUnityContainer container = new UnityContainer(); 
     Bootstrapper.Initialise(container); 
     return container.Resolve<IPatientRepository>(); 
    } 
} 

Donc, @Roy a eu raison de vous diriger vers la méthode CreateDataSource(). Cependant, l'utilisation de ServiceLocator, en tant que classe ou en tant que modèle, doit être évitée. Malheureusement, Microsoft a presque forcé tout le monde sur la route ServiceLocator avec des classes telles que ServiceLocator et DependencyResolver.

+0

Le type générique 'DataService ' n'a pas 'être une interface, non plus, pour fonctionner avec la méthode' CreateDataSource() '. –

Questions connexes