Je suis un Castle n00b, et j'utilise l'API Fluent de Castle Windsor pour enregistrer automatiquement les implémentations dans des services basés sur une convention de dénomination (quelque chose est implémenté par Something). Une chose que je voulais prendre en charge est que l'auto-enregistrement ramasse les dépendances qui se trouvent dans des DLL séparées, et les enregistre automatiquement. Donc: IFoo est implémenté par Foo (tous les deux dans Foo.dll), et Foo dépend de IBar, qui est dans Bar.dll.Castle Windsor et enregistrement automatique
J'ai le code suivant écrit pour effectuer l'auto-enregistrement. Cela semble fonctionner, mais je me demande si j'ai trop travaillé moi-même. Existe-t-il un moyen plus simple d'accomplir la même chose?
private static void EnsureRegistered(Type t, IWindsorContainer container)
{
if (!container.Kernel.HasComponent(t) && (!(t.Assembly.FullName.StartsWith("System") || t.Assembly.FullName.StartsWith("mscorlib"))))
{
bool registeredAtLeastOneComponent = false;
container.Register(AllTypes.Pick().
FromAssembly(t.Assembly).If(delegate(Type t2)
{
//auto-registers all types that implement an interface where
//the name of the interface is the same as the class, minus the 'I'
//ex: EchoService is auto-registered as handler of IEchoService
Type[] interfaces = t2.GetInterfaces();
bool shouldRegister = false;
foreach(Type interfaceType in interfaces)
{
shouldRegister = t2.Name.Equals(interfaceType.Name.Substring(1))
&& (!container.Kernel.HasComponent(interfaceType));
registeredAtLeastOneComponent = registeredAtLeastOneComponent || shouldRegister;
if (shouldRegister)
break;
}
return shouldRegister;
}).WithService.Select(delegate(Type type, Type baseType)
{
Type serviceType = null;
Type[] interfaces = type.GetInterfaces();
foreach(Type interfaceType in interfaces)
{
if (!type.Name.Equals(interfaceType.Name.Substring(1))) continue;
serviceType = interfaceType;
break;
}
return new Type[] {serviceType};
}));
if (!registeredAtLeastOneComponent)
return;
//for each of the items in the graph, if they have see if they have dependencies
//in other assemblies that aren't registered, register those dependencies as well
foreach(GraphNode registered in container.Kernel.GraphNodes)
{
if (!(registered is Castle.Core.ComponentModel))
continue;
Castle.Core.ComponentModel registeredComponent = registered as Castle.Core.ComponentModel;
foreach(ConstructorCandidate constructor in registeredComponent.Constructors)
{
foreach(DependencyModel dep in constructor.Dependencies)
{
EnsureRegistered(dep.TargetType, container);
}
}
}
}
}
Merci pour la réponse. Ce que je fais est d'introduire un conteneur dans certaines applications héritées, et d'aller sans friction lors de l'utilisation du conteneur (à condition qu'ils soient conformes à la convention 'IBar est implémentée par Bar'). Et convenu de: scénarios complexes. Essayer de frapper le cas de 80% ici, cependant. –
Dans ce cas, le code devrait très bien servir son but! –
Merci. Comme je l'ai dit, je cherchais principalement à voir si je manquais un moyen plus simple. Et comme vous l'avez souligné, une façon de simplifier les choses serait de simplifier les choses autour du conteneur :-) –