J'écris un résolveur de sous-dépendance pour castle windsor. Le résolveur renvoie un objet qui implémente une interface générique. Les paramètres génériques sont résolus lors de l'exécution et factory est utilisé pour renvoyer l'implémentation correcte. Je ne veux pas utiliser une chaîne pour obtenir le MethodInfo de la méthode d'usine. Les travaux suivants, mais je pense qu'il doit y avoir une meilleure façon de résoudre la méthode de création d'usine, voir GetMethodName et comment il est utilisé.En utilisant la réflexion pour obtenir MethodInfo générique sans utiliser un nom de chaîne et les paramètres génériques sont résolus à l'exécution
public class FooFactoryResolver : ISubDependencyResolver
{
private static string factoryMethodName;
private readonly IWindsorContainer container;
public FooFactoryResolver (IWindsorContainer container)
{
this.container = container;
}
private static string GetMethodName()
{
if (factoryMethodName == null)
{
IFooFactory fooFactory = null;
Expression<Func<IFoo<object, object>>> expression =
() => fooFactory .CreateFoo<object, object>();
factoryMethodName = ((MethodCallExpression)expression.Body).
Method.Name;
}
return factoryMethodName;
}
public object Resolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver,
Castle.Core.ComponentModel model, DependencyModel dependency)
{
return
TryToResolveDirectly(dependency) ??
TryToResolveUsingFactories(dependency) ??
ComponentNotFound(dependency);
}
private static object ComponentNotFound(DependencyModel dependency)
{
throw new ComponentNotFoundException(dependency.TargetType);
}
private object TryToResolveUsingFactories(DependencyModel dependency)
{
var fooFactories = this.container.ResolveAll<IFooFactory>();
Type[] genericTypes = dependency.TargetItemType.
GetGenericArguments().ToArray();
return (from fooFactory in fooFactories
where fooFactory.CanCreate(genericTypes[0],
genericTypes[1])
let factoryMethod = fooFactory.GetType().
GetMethod(GetMethodName())
select factoryMethod.MakeGenericMethod(
genericTypes.ToArray()).
Invoke(fooFactory, new object[0])).
FirstOrDefault();
}
private object TryToResolveDirectly(DependencyModel dependency)
{
return this.container.Kernel.HasComponent(dependency.TargetType) ?
this.container.Resolve(dependency.TargetType) : null;
}
public bool CanResolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver,
Castle.Core.ComponentModel model, DependencyModel dependency)
{
return dependency.TargetType.GetGenericTypeDefinition() ==
typeof(IFoo<,>);
}
}
public interface IFoo<T1, T2> { }
public interface IFooFactory
{
IFoo<T1, T2> CreateFoo<T1, T2>();
bool CanCreate(Type a, Type b);
}
Je ne suis pas sûr que ce soit un abus ou non, mais il fait le travail, je me sens que je manque quelque chose d'évident. J'espérais qu'il y aurait un moyen de changer les paramètres génériques sur MethodInfo à partir de MethodCallExpression ou un moyen de revenir de MethodInfo à son 'Parent' et d'appeler MakeGenericMethod en utilisant les types que je veux.
Prise en charge des génériques ouverts dans l'API Reflection. C'est un fait triste. Si cela fonctionne, laissez-le tel quel et passez à des tâches plus intéressantes. Je ne passerais pas trop de temps là-dessus. –
@Krzysztof C'est bien si vous n'êtes pas OCD :). Merci pour l'appel de réveil. – Bronumski