1

Castlewindsorのサブ依存関係リゾルバーを作成しています。リゾルバーは、汎用インターフェースを実装するオブジェクトを返します。ジェネリックパラメータは実行時に解決され、ファクトリは正しい実装を返すために使用されます。ファクトリメソッドのMethodInfoを取得するために文字列を使用したくありません。以下は機能しますが、ファクトリcreateメソッドを解決するためのより良い方法が必要だと思います。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 メソッドに適用するカスタム属性を作成し、Reflection を使用してインターフェイス タイプでその属性を探します (常に見つかります)。これにより、式を作成する必要がなくなり、属性を探すだけで済みます。それがオンになっている MethodInfo を見つけたら、そこから名前を取得できます。

の閉じた型宣言を取得する必要はありませんIFooFactory.CreateFoo<T1, T2>()。名前を取得しようとしているだけで、型でメソッド宣言を閉じてもname は変更されません

于 2010-12-08T15:08:12.953 に答える