Lets assumer ces classes/interfaces:Obtenez toutes les variantes d'enregistrement AsClosedTypesOf du Autofac Builder
public interface ICommand
{
}
public class SomeCommand : ICommand
{
}
public interface ICommandHandler<T> where T : ICommand
{
void Handle(T arg);
}
public class SomeCommandHandler : ICommandHandler<SomeCommand>
{
void Handle(SomeCommand arg){ /* do something */ }
}
public interface ICommandBus
{
void RegisterHandler<T>(T t) where T : ICommandHandler<T>;
void RegisterHandlerByParam<T2>(ICommandHandler<T2> t2) where T2 : ICommand;
void RegisterHandlerMethod<T3>(Action<T3> action) where T3 : ICommand
}
public class TheCommandBus : ICommandBus
{
// implements ICommandBus ...
}
Je veux enregistrer toutes les implémentations de ICommandHandler <> automatiquement. Toutes les variantes (Register *) sont des solutions valides même si je préfère le paramètre Action alors qu'il est plus flexible et n'a pas de dépendance à l'interface Handler (juste délégué d'action).
Autofac a la capacité d'enregistrer les types basés sur l'analyse de l'assemblage et enregistrer les implémentations trouvées d'une interface générique, par exemple:
builder.RegisterAssemblyTypes(Assembly.LoadFrom("MyAssembly.dll"))
.AsClosedTypesOf(typeof(ICommandHandler<>));
J'ai donc toutes les implémentations enregistrées. Maintenant, je dois les enregistrer tous automatiquement à TheCommandBus. Comment faire cela?
Je peux le faire manuellement en ajoutant ces lignes (par exemple lors OnActivated):
builder.RegisterType<TheCommandBus>().As<ICommandBus>().OnActivated(args =>
{
// now I need to list all implementations here!!! please, no...
args.Instance.RegisterHandler<ICommandHandler<SomeCommand>>(args.Context.Resolve<ICommandHandler<SomeCommand>>());
// does not look better to me than before ...
args.Instance.RegisterHandlerByParam<SomeCommand>(args.Context.Resolve<ICommandHandler<SomeCommand>>())
// uses delegate for, but still need to list all variants
args.Instance.RegisterHandlerMethod<SomeCommand>(args.Context.Resolve<ICommandHandler<SomeCommand>>().Handle)
});
Si je veux utiliser un tel type dans une expression lambda lors de l'inscription, j'ai le problème, que je dois identifier le type concret, comme pour cet exemple sur le processus d'activation d'un autre composant. Mais je ne veux pas les lister tous manuellement ... je veux quelque chose comme ça automatiquement.
Comment attraper toutes les implémentations ICommandHandler ET les enregistrer automatiquement avec la méthode Register *?
Edit:
Une autre variante consiste à étendre la classe SomeCommandHandler s'enregistrer quand résolu dans son constructeur:
public SomeCommandHandler(ICommandBus commandBus)
{
// and register here, for example
commandBus.RegisterHandlerbyParam(this);
}
De cette façon, je dois fournir AutoActivate() au résultat de l'enregistrement de AsClosedTypesOf . (une solution possible, mais maintenant les «gestionnaires» ont deux responsabilités ... l'enregistrement et la manipulation)
Belle solution. THX. Je donnerais un 2ème upvote pour "réflexion de fantaisie-schmancy" :-D – Beachwalker