2009-06-02 6 views
3

Func <>을 반환하는 메서드를 내보내려고합니다. 이 메서드 내에서 반환 형식을 정확하게 제공하는 대리자 또는 람다 식을 만들어야합니다. 전부대리자 또는 람다 식을 내 보냅니다.

는 다음과 같아야합니다

// I have a resolve method that will be called inside my missing method 
// This is it's signature: 
object Resolve(params object[] args); 

// This is how I use it: 
var barFactory = (Func<IBar>)MissingMethod(typeof(IBar)); 
var bar = barFactory.Invoke(); 

// or - with one string argument: 
var fooFactory = (Func<string, IFoo>)MissingMethod(typeof(IFoo), typeof(string)); 
var foo = fooFactory.Invoke("argument for foo"); 

을 MissingMethod 내부() 것처럼 보일 것입니다 : 내가 유일한 방법은 내 MissingMethod을 (얻을 수 있다고 생각

object MissingMethod(Type returnType, params Type[] argTypes) 
{ 
    // Create the type of Func<> based on the passed returnType and the argTypes 
    var funcType = typeof(Func<,...,>).MakeGenericType(...) 

    // Here I have to use the Resolve() method and cast the lambda to the correct type 
    return (cast to funcType)((arg1, arg2) => Resolve(arg1, arg2)); 
} 

)에있다 reflection.emit을 사용하십시오.

람다 또는 델리게이트를 방출하는 데 대한 유용한 자료 또는 자습서를 알고 있습니까?

이 문제와 관련하여 다른 해결책이 있습니까?

편집 : 컨테이너와 해결() 메소드를 구현하기 위해 노력하고

static void Main() 
{ 
    var container = new Container(); 
    container.Register<Foo>(); 
    container.Register<ConsumerClass>(); 

    var consumerClass = Container.Resolve<ConsumerClass>(); 
} 

class Foo() 
{ 
    public Foo(string argument) {} 
} 

class ConsumerClass 
{ 
    public ConsumerClass([Inject] Func<string, Foo> factory) 
    { 
    var foo1 = factory.Invoke("first foo"); 
    var foo2 = factory.Invoke("another foo"); 
    // ... 
    } 
} 

: 여기
내가 실현하려 원하는의 시나리오입니다. 나는 "Foo"유형이 등록되어 있음을 알고 있습니다. 그리고 나는 그 생성자가 호출 될 문자열을 필요로한다는 것을 압니다.

"ConsumerClass"유형을 해결해야 할 때 Func를 주입하려고합니다.

Container.Resolve<Foo>("argument"); 

을하지만 그럼에도 불구하고 컨테이너, 너무 Func을 제공 할 수 있어야한다 : 즉, 일반적으로는 다음과 같은 푸에 단일 instaces을 제공하기 때문에 내 용기를 제공 할 수 있습니다 정확히하지 않습니다. 모든 정보가 필요합니다.

하지만이 바운드 Func <을 만드는 데 걸림돌이되었습니다.> 그리고 기억할 수있는 것은 Func < ,,,> 일 수도 있습니다. 그래서 저는이 대의원을 즉석에서 만들 수있는 솔루션을 찾고 있습니다. 정확한 바운드 형식으로 캐스팅 할 수 있어야합니다.

편집 :
내가 this처럼 뭔가를 시도하고 ... 더 잘 설명하는 방법을 잘 모르겠습니다. 하지만 나는 표적을 지키고 싶지 않아. 대신

delegate void object LateBoundMethod(object target, object[] arguments); 

의 내 대표는

delegate void object LateBoundMethod(object[] arguments); 

같이해야하며, 대상은 인스턴스 필드로 제공됩니다. Marc의 솔루션을 가져 와서 '개선'함으로써 다음과 같은 결과를 얻었습니다.

그러나 이것은 불완전합니다. Resolve() - 메서드는 더 이상 정적이 아니기 때문에 (인스턴스 필드가 두 개 필요하기 때문에) 호출 할 수 없습니다. 그래서 문제는 여기에

var callEx = Expression.Call(null, typeof(FuncFactory).GetMethod("Resolve"), argsArray); 

null을 첫 번째 인수로 전달하는 대신 'this'에 대한 참조가 필요하다고 생각합니다. 어떻게해야합니까?

+1

내가 당신이 일을하려고하고 있지만 제네릭 MissingMethod 방법을 않을 것입니다 것을 얻을 100 % 확신하지 말 당신의 문제를 해결하는 방법의 절반을 얻으시겠습니까? 또는 옵션이 아닌가요? – kastermester

+0

아, 또한 가능한 모든 Func 제네릭을 다루기 위해 코드를 여러 번 코딩해야한다는 사실을 알았지 만 Marc이 언급했듯이 어쨌든 하드 코딩해야합니다. – kastermester

+0

(의견에 대한 답글) –

답변

7

첫 번째 문제는 Func<...>이 존재하지 않는다는 것입니다 - 당신은 별도로 Func<>, Func<,>, Func<,,>, Func<,,,>에 코드를 필요 했어.

지금; 코드를 이해할 수 있지만 해결하려는 시나리오가 무엇인지 잘 모르겠습니다 ... 명확하게 할 수 있습니까? 아마도 더 나은 옵션이있을 것입니다 ...

소리가 복잡하면 맞춤 Expression이 아마도 가장 적합한 옵션 일 것입니다 (Reflection.Emit보다 훨씬 간단합니다). 내가 해


이 예를 들어, 작동 ...

static Delegate MissingFunc(Type result, params Type[] args) 
{ 
    int i = 0; 
    var param = Array.ConvertAll(args, 
     arg => Expression.Parameter(arg, "arg" + i++)); 
    var asObj = Array.ConvertAll(param, 
     p => Expression.Convert(p, typeof(object))); 
    var argsArray = Expression.NewArrayInit(typeof(object), asObj); 
    var body = Expression.Convert(Expression.Call(
       null, typeof(Program).GetMethod("Resolve"), 
       argsArray), result); 
    return Expression.Lambda(body, param).Compile(); 
} 
static void Main() 
{ 
    var func2 = MissingFunc(typeof(string), typeof(int), typeof(float)); 
} 
public static object Resolve(params object[] args) { 
    throw new NotImplementedException(); 
} 
+0

답장을 보내 주셔서 감사합니다. 당신은 Func에 관해서 정확합니다 <...> - 허용 된 인수를 4 개로 제한해야합니다. Resolve() - Method (IoC 컨테이너에서 제공)에서 코드를 분리하려고합니다. 대신 객체가 IoC 컨테이너를 간접적으로 사용하여 하나의 유형의 인스턴스를 더 많이 만들 수 있도록하는 작은 공장 (Func <> 인수로 전달됨)을 만들 수 있기를 원합니다. – tanascius

+0

고마워요 ... 저는 표현을 처음 접했습니다. "Object Resolve (Type, params object)"라는 서명으로 인스턴스 메소드를 Resolve()하는 방법에 대한 힌트를 줄 수 있습니까? 나는 아직도 붙어있다 :/ – tanascius

+0

미안하다, 나는 기차로 떠나야 만했다. 나는이 분야에 대해 정교하게 설명 할 수는 있지만 - 처음에는 내 질문을 반복한다. 여기서 시나리오는 무엇인가? 최소한 3 가지 방법으로 접근 할 수 있습니다. (그리고 Reflection.Emit 중 하나도 아닙니다.) * 인스턴스 * 메소드 인 경우 * 인스턴스 *가 무엇입니까? 아마도 좀 더 준결승을 보여줄 수 있습니다. 아직 확실치 않은 점이 있다면 답으로 표시를 해두십시오. 나는 불쾌하지 않을 것입니다. 질문이 해결되면 행복 할 때만 완료라고 표시하십시오. (확실하지 않습니다 ...) –

관련 문제