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を呼び出す方法があることを期待していました。