2010-12-08 4 views
1

성 윈저에 대한 하위 종속성 해결 프로그램을 작성 중입니다. 해석기는 일반 인터페이스를 구현하는 객체를 반환합니다. 제네릭 매개 변수는 런타임에 확인되고 팩토리는 올바른 구현을 반환하는 데 사용됩니다. 나는 factory 메소드의 MethodInfo를 얻기 위해 문자열을 사용하고 싶지 않다. 다음은 작동하지만 공장 생성 메서드를 해결하는 더 좋은 방법이 있어야한다고 생각합니다. GetMethodName 및이 메서드 사용 방법을 참조하십시오.리플렉션을 사용하여 문자열 이름을 사용하지 않고 일반 MethodInfo를 가져오고 런타임시 일반 매개 변수가 해석됩니다.

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의 generic 매개 변수를 MethodCallExpression에서 변경하거나 MethodInfo에서 'Parent'로 돌아가서 원하는 유형을 사용하여 MakeGenericMethod를 호출하는 방법이있을 것으로 기대하고 있습니다.

+2

Reflection API에서 공개 제네릭을 지원합니다. 슬픈 사실입니다. 작동하는 경우 - 그냥 그대로두고 더 재미있는 작업으로 이동하십시오. 나는 이것에 너무 많은 시간을 쓰지 않을 것이다. –

+0

@Krzysztof OCD가 아니라면 괜찮습니다. :). 웨이크 업 전화에 감사드립니다. – Bronumski

답변

0

CreateFoo 메서드에 적용한 사용자 지정 특성을 만든 다음 Reflection을 사용하여 인터페이스 형식에서 해당 특성을 찾습니다 (항상 찾을 수 있음). 이렇게하면 표현식을 작성하지 않아도되며 속성을 찾을 수 있습니다. 일단 MethodInfo가 발견되면 거기에서 이름을 얻을 수 있습니다.

IFooFactory.CreateFoo<T1, T2>()에 대해 폐쇄 형 선언을받을 필요는 없습니다. 당신은 단순히 이름을 얻으려고 시도하고 있습니다. 타입이 인 메소드 선언을 닫지 않으면 이름이 변경되지 않습니다..

관련 문제