2012-01-17 4 views
1

が見えますパラメータ、私は外部呼び出しのコンテキストでアクセス/呼び出したいです。のFuncに渡さに割り当てられたメソッドへのアクセス<>パラメータ

簡単な例以下

:あなたが工場を渡していないので、あなたが呼び出し先、

の工場に割り当てることはありません(実際のresultsデータ型がstringではなく、いくつかの複合型)

class Caller 
{ 
    private Func<string> factory; 

    public Caller() 
    { 
     this.factory = null; 
     var adapter = new Adapter(this.factory); 
     adapter.Adapt(...); 

     // then I would share this factory via IoC 
     dependencyContainer.RegisterUsingFactoryMethod<string>(this.factory); 

     // !!! but here is factory still not assigned 
     string results = this.factory(); 
    } 
} 

class Adapter 
{ 
    private string results; 

    public Adapter(Func<string> factory) 
    { 
     factory =() => this.results; 
    } 

    public IOut Adapt(IIn input) 
    { 
     this.results = someCalculatedData; 
    } 
} 
+2

「out」を使用しようとしましたか? – Reniuz

答えて

4

これは、デリゲートとは何の関係もあり、すべての引数は、デフォルトでは値で渡されているという事実に関係するすべてのものを持っていません。 factoryint、またはstring、またはStringBuilderた場合は、同じ動作を参照してくださいね。

Serviceコンストラクタで引数の値を変更する場合は、refまたはoutパラメータが必要です。しかし、私は個人的にあなたが戻りFunc<string>メソッドを使用するように変更することを示唆している:

public class Caller 
{ 
    private readonly Func<string> factory; 

    public Caller() 
    { 
     this.factory = Service.GetFunc(); 
    } 
} 

public class Service 
{ 
    public static Func<string> GetFunc() 
    { 
     return() => Guid.NewGuid().ToString(); 
    } 
} 

を(他のさまざまなオプションは、このような方法の基変換、またはプロパティとして、ここにあります。それはするのは難しいです。文脈があまりないときに何をお勧めするか知っておいてください。)

明らかに、メソッドの名前を変更したいと思います。しかし、outパラメータを変更するためだけにコンストラクタを呼び出すのは非常に奇妙なコードです。

パラメータの受け渡しの詳細については、article on the topicを参照してください。

+0

+1興味深い問題を持つさまざまなソリューションを提供してくれてありがとうございます。本当に私は単にメソッドを公開することができますが、これはサービスのAPIをやや邪魔しています。私は後でそれを使用することができるように、工場を初期化することができる特定の段階(例として建設ではない)でのサービスというアイデアは、実際にはこのアプローチの全体的なデザインが間違っているとは思えません – sll

+0

@sll: *サービスオブジェクトを構築したいですか?実際に提供されるものに興味を持っている必要があります。コンストラクタを呼び出して、新しく作成されたオブジェクトを完全に無視するときはいつでも、心配する必要があります。 –

+0

これはサービスではなく、何らかの種類のアダプタですが、データ変換時に中間データをキャッシュしておく必要があります。このデータはIoCコンテナに登録することですが、アダプタにIoCを注入する必要があります。この考え方のように、今は 'ref Func'を注入するよりもそれほど悪くはないようです。 – sll

2

参照によってサービスに渡された場合、変数への更新は呼び出し側には表示されません。

私はFunc<T...>参照を呼び出すには...

+1

+1あなたが正しいので、 'ref'修飾子を追加すると問題が解決するでしょう – sll

+0

(私の編集とコメントを説明するだけです - 私は参考にして渡していたと答えています) –

0

あなたが参照してコンストラクタにパラメータを渡したりすることはできませんかどうか確信がもてない、あなたはそれが通常の方法であるかのように呼び出す必要があります。すなわち:

class Service 
{ 
    public Service(Func<string> factory) 
    { 
     string result = factory(); 
    } 
} 

Func<string>ことはstringタイプを返します。あなたのコメントから

EDIT

私はあなたが実際にはOPに求めていたものを実現しています。任意のパラメータに値を割り当てるには、outまたはrefとマークする必要があります。だからあなたの宣言は次のようになります。

public Service(out Func<string> factory) 

または

public Service(ref Func<string> factory) 
+0

'Caller'でファクトリを呼び出したいので、サービスは単に呼び出し元にいくつかのファクトリを提供します。私はメソッドを公開して使用することができますが、これは他の方法です。 – sll

+0

@sllに固執したくありません。私の答えを編集しました。 –

3

あなたがサービスのコンストラクタにoutパラメータでFUNCをパージングしてみてくださいことはできますか?

これにより、コンパイラはServiceコンストラクタのファクトリパラメータへの参照を確実に初期化することができます。さもなければ、ヌルFuncへの参照を値でコンストラクタに渡すだけで、ctor内のスタック上のその変数に関数をローカルに割り当てます。

refとoutパラメータにわかりやすくするためにthis related questionを参照してください。

敬具、

+3

それはうまくいくが、私はそれが良いデザインだとは思わない。 outパラメータの値を変更するためにコンストラクタを呼び出すだけの理由は? @JonSkeetが合意した。 –

+0

個人的には、代理人を明示的に作成するために、「Func Service.InitializeCallback()」や「Service.InitializeCallback(out Func コールバック)」などのメソッドを使用します。 –

関連する問題