2012-01-04 7 views
3

私はいくつかのデリゲートを連鎖させる方法を探しています。その結果、あるデリゲートからの結果が次のデータの入力になります。私は部分を別の方法で行う方程式解法プログラムでこれを使用しようとしています。その考え方は、方程式を作成するときに、デリゲートを追加して特定の順序でチェーン化するので、適切に解決できるということです。問題に近づくより良い方法がある場合は、共有してください。1つのデリゲートの結果をC#で別のデリゲートの入力に連鎖できますか?

+0

おそらく表現木は(http://msdn.microsoft.com/en-us/library/bb397951.aspx)を調べる価値がありますか? – Nailuj

答えて

7

敬具、:

public static Func<T1, TResult> Compose<T1, T2, TResult>(Func<T1, T2> innerFunc, Func<T2, TResult> outerFunc) { 
    return arg => outerFunc(innerFunc(arg)); 
} 

これは、最初の引数が供給されるとinnerFuncを実行し、outerFuncに結果を渡し、function composition実行します。

Func<double, double> floor = Math.Floor; 
Func<double, int> convertToInt = Convert.ToInt32; 

Func<double, int> floorAndConvertToInt = Compose(floor, convertToInt); 

int result = floorAndConvertToInt(5.62); 

Func<double, int> floorThenConvertThenAddTen = Compose(floorAndConvertToInt, i => i + 10); 

int result2 = floorThenConvertThenAddTen(64.142); 
3

はいこれが可能です。デリゲートの戻り値の型が呼び出されるデリゲートのパラメータ型であることを確認する必要があります。

多くのLINQがこの方法で構築されていますが、expressionsを参照してください。

+0

私はすべてが同じ入力タイプを必要とし、その特定のタイプを返すべきだと考えました。 – Snowppy

+0

@Snowppy - それぞれを他のものに連鎖させたい場合は、そうです。これは[流暢なインターフェース](http://en.wikipedia.org/wiki/Fluent_interface)の基礎です。 – Oded

0

説明しているAPIの種類はFluent APIです。良いチュートリアルのための前の記事を見てください。

デリゲートチェーニングに関して、.NET 3.5のLINQ拡張メソッド、特に関数に渡されたラムダ関数(デリゲート)がIEnumerableの結果となる方法を見てみましょう。この結果は別の拡張メソッド+ラムダ。

特定のケースでは、代理人を受け入れ、代理人が操作できる別のFunctorを返すには、Functorというクラスを作成する必要があります。これは役立つかもしれない

0

GetInvocationlistを使用してあなたはこれを達成することができます。

Delegate[] chain = chained.GetInvocationList(); 

     int res = 10; 
     for(int i = 0; i < chain.Length; i++) 
      { 
       //Call chain[i] 
       res = chain[i](res); 
      } 
0

私はあなたがに興味があるかもしれないと思った(...ようにと)代表者のシーケンスを起動し、次の1つのデリゲートの出力を渡す関与同様の問題自分自身に取り組んできました

static class Program 
{ 
    private static IList<Func<int, int>> delegateList = 
     new List<Func<int, int>>() 
    { 
     AddOne, AddOne, AddOne, AddOne, AddOne, 
     AddOne, AddOne, AddOne, AddOne, AddOne, 
    }; 

    static void Main(string[] args) 
    { 
     int number = 12; 

     Console.WriteLine("Starting number: {0}", number); 
     Console.WriteLine("Ending number: {0}", 
          delegateList.InvokeChainDelegates(number)); 
     Console.ReadLine(); 
    } 

    public static int AddOne(int num) { return num + 1; } 

    public static T InvokeChainDelegates<T>(this IEnumerable<Func<T, T>> source, 
              T startValue) 
    { 
     T result = startValue; 

     foreach (Func<T, T> function in source) 
     { 
      result = function(result); 
     } 

     return result; 
    } 
} 

シーケンスは、それほどすでに受け入れ答えとしてではなくいくつかの調整と同じように強力ではありません同じタイプの代表者を含むように、コードの両方のビットを持っている:私は、概念実証のよう開発されたコードを参照強力なソリューションを提供するために組み合わせることができます。

関連する問題