J'ai travaillé sur les détails de l'implémentation de l'IoC dans mes applications Web, mais d'une manière qui tire parti de Microsoft.Practices.ServiceLocation. J'utilise spécifiquement Autofac et l'intégration asp.net, mais je voulais me laisser ouvert à d'autres conteneurs. Le long de la ligne de this question, j'étais préoccupé par la façon d'accéder au conteneur dans mon code d'application web.Autofac, ASP.NET et Microsoft.Practices.ServiceLocation
J'ai une bibliothèque 'core' qui définit principalement les interfaces à résoudre. Cette bibliothèque de base est également utilisée par mon application Web et d'autres applications. Très pratique pour avoir des interfaces communes définies. Je pensais que c'était un excellent endroit pour mettre l'accès au conteneur IoC, et je l'ai fait avec une classe statique. L'astuce consiste à injecter le conteneur dans la classe statique. Il est difficile dans un environnement Web parce que le conteneur peut être différent pour chaque demande, tandis que dans une application non-web, il sera probablement le même tout le temps. Au début j'ai essayé d'injecter le direclty du conteneur avec une méthode mais cela a échoué rapidement sur la prochaine requête web! Alors je suis venu avec ceci:
public static class IoCContainer
{
public static void SetServiceLocator(Func<IServiceLocator> getLocator)
{
m_GetLocator = getLocator;
}
static private Func<IServiceLocator> m_GetLocator = null;
public static T GetInstance<T>(string typeName)
{
return m_GetLocator().GetInstance<T>(typeName);
}
}
Maintenant, dans mon Global.asax.cs je fais ceci:
protected void Application_Start(object sender, EventArgs e)
{
var builder = new Autofac.Builder.ContainerBuilder();
... register stuff ...
var container = builder.Build();
_containerProvider = new Autofac.Integration.Web.ContainerProvider(container);
Xyz.Core.IoCContainer.SetServiceLocator(() =>
new AutofacContrib.CommonServiceLocator.AutofacServiceLocator
(_containerProvider.RequestContainer));
}
public IContainerProvider ContainerProvider
{
get { return _containerProvider; }
}
static IContainerProvider _containerProvider;
Et appelle à résoudre ressemblent à des dépendances
var someService = Xyz.Core.GetInstance<ISomeService>();
Ainsi, plutôt que passer un conteneur spécifique Je passe un délégué qui sait comment GET un conteneur. Pour les applications non-web, le délégué retournera probablement ce que builder.Build() sert.
Ma question aux experts est, est-ce logique? J'ai un moyen facile d'arriver à quelque chose qui peut résoudre les dépendances sans savoir ce que le produit conteneur est ou d'où le conteneur lui-même provient. Qu'est-ce que tu penses?
C'est très cool Peter, mais j'espérais pouvoir réutiliser mes bibliothèques « .Core » dans d'autres contextes, peut-être même pas en ligne . Cependant, je pense que c'est une excellente réponse car cela m'aide à éviter trop d'abstractions. Merci! – n8wrl
Je vois ce que vous voulez dire. Pourtant, si vous pouvez supprimer complètement le modèle de localisateur de service et n'utiliser que l'injection de dépendances, vous n'auriez pas besoin de résoudre ce problème du tout :) –