我正在为温莎城堡写一个子依赖解析器。解析器返回一个实现通用接口的对象。泛型参数在运行时解析,工厂用于返回正确的实现。我不想使用字符串来获取工厂方法的 MethodInfo。以下是可行的,但我觉得必须有更好的方法来解决工厂创建方法,请参阅 GetMethodName 及其使用方式。
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);
}
我不确定这是否是滥用,但它可以完成工作,我只是觉得我错过了一些明显的东西。我希望有某种方法可以将 MethodInfo 上的泛型参数从 MethodCallExpression 更改为从 MethodInfo 返回到它的“父”并使用我想要的类型调用 MakeGenericMethod 的方法。