2009-06-02 3 views
3

Func <>を返すメソッドを生成したいと思います。このメソッドの中で、戻り値の型に正確に対応するデリゲートまたはラムダ式を作成する必要があります。デリゲートまたはラムダ式を出力する方法

完全にそれは次のようになります。MissingMethod(インサイド

// 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を(取得する唯一の方法だと思い

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を使用します。

ラムダまたはデリゲートを放つことについての優れたリソースやチュートリアルを知っていますか?

この問題の別の解決方法がありますか?

EDIT:
ここでは、私がachiveしたいもののシナリオです:

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を提供することができるはずです:通常、それはこのようfooへの単一instacesを提供するので、それは、私のコンテナが提供することができます正確に何ではありません。それは必要なすべての情報を持っています。

しかし、今私はこのバインドFunc <を作成するには固執しています。そして、それはFunc < ,,,>かもしれません。だから私は、この代議員をその場で作ることができる解決策を探しています。彼らは厳密に束縛型にキャスト可能でなければならない。

EDIT:
私はそれをよりよく説明するかどうかはわからない...私はthisような何かをしようとしています。しかし、私は目標を通過したくありません。代わりの

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

私のデリゲートは

delegate void object LateBoundMethod(object[] arguments); 

のようになりますし、ターゲットはインスタンスフィールドとして提供されます。 Marcの解決策を取って改善することによって、私は以下のようになります。

これは不完全です。 Resolve()メソッドは静的ではなく(2つのインスタンスフィールドを必要とするため)、呼び出すことはできません。だからここの問題は

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<,,,>にコーディングする必要があると思います。

Now;私はコードを理解していますが、あなたが解決しようとしているシナリオは何か分かりません...明確にすることはできますか?おそらくもっと良いオプションがあります...

複雑な場合は、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() - メソッド(IoCコンテナによって提供される)から切り離したいと思っています。その代わりに、オブジェクトがIoCコンテナを間接的に使用することによって、1つのタイプのインスタンスをさらに作成できるようにする、小さなファクトリ(Func <>引数として渡される)を作成できるようにします。 – tanascius

+0

ありがとうございます...私は式を初めて使っています。 「オブジェクト解決(型、paramsオブジェクト)」というシグネチャでResolve()メソッドをインスタンスメソッドにする方法のヒントを教えてください。私はまだ立ち往生しています:/ – tanascius

+0

申し訳ありませんが、私は電車のために出発しなければなりませんでした。私はこの分野で高度に精緻化することができます - しかし、私は最初に私の質問を繰り返すだろう:ここでのシナリオは何ですか?私は少なくとも3つの方法でこれにアプローチすることができます(そしてそれらのどれもReflection.Emitではありません)...もしそれが*インスタンス*メソッドであれば、それは*の*インスタンスですか?おそらく、あなたは半完成をもう少し示すかもしれません。あなたがまだ物事を確信していない場合は、答えとしてこれをマークすることを自由にしてください - 私は怒らないでください。あなたが質問が解決されたことを幸せに思うときは、それだけを記入してください(私はそれが...) –

関連する問題