1

我正在为温莎城堡写一个子依赖解析器。解析器返回一个实现通用接口的对象。泛型参数在运行时解析,工厂用于返回正确的实现。我不想使用字符串来获取工厂方法的 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 的方法。

4

1 回答 1

0

创建一个应用于 CreateFoo 方法的自定义属性,然后使用反射在接口类型上查找该属性(您将始终找到它)。这避免了必须创建表达式,您只需查找您的属性。一旦找到它所在的 MethodInfo,就可以从那里获取名称。

不需要为IFooFactory.CreateFoo<T1, T2>();获取封闭类型声明。您只是想获取名称,使用类型关闭方法声明不会更改名称

于 2010-12-08T15:08:12.953 回答