1

私は、すべて同じ型を返す異なるパラメータを取るメソッドを持つ、異なる型のいくつかのオブジェクトを持っています。これらの方法は失敗する可能性があります。オブジェクトとそのメソッドを受け取り、メソッドが失敗したかどうかを示し、失敗が発生したオブジェクトを示す関数を作成する方法はありますか? Result オブジェクトを変更することはできず、それを呼び出したオブジェクトに関する情報を保持していません。

これは少し冗長だと思います:

Result resultA = A.something();
if(resultA.Failed) return new Status{Failed=A.GetType().ToString()};

Result resultB = B.somethingElse(3);
if(resultB.Failed) return new Status{Failed=B.GetType().ToString()};

Result result3 = C.someOtherThing("apple");
if(resultC.Failed) return new Status{Failed=C.GetType().ToString()};

// Do some processing of the results (will succeed if A,B,C succeeded)

return new Status {Failed=null, Success=true};

それをすべて関数にカプセル化する方法はありますか? それは非常に繰り返されているようです。A、B、および C は有用な基底クラスから継承されず、それらのメソッドはすべて異なるパラメーターを取り、異なる名前を持っています。

そうは言っても、私は Status クラスにアクセスでき、この関数の戻り値にもアクセスできます。関数は戻る必要はなく、代わりに例外をスローできます。障害が発生した場合、関数はすぐに壊れる可能性があります。

4

4 に答える 4

0

これを行う簡単な方法の 1 つ:

//Note: the method signature could just be IEnumerable<Result> AggregateResults(params Func<Result>[]) 
//if you want to be able to aggregate the results of 0 calls
IEnumerable<Result> AggregateResults(Func<Result> func, params Func<Result>[] otherFuncs)
{
    yield return func();
    foreach(var otherFunc in otherFuncs)
        yield return otherFunc();
}

//Usage:
var results = AggregateResults(
    () => A.Something(),
    () => B.SomethingElse(3),
    () => C.SomethingOtherThing("apple"));

残念ながら、最初に失敗した呼び出しで停止し、呼び出し元のオブジェクトを取得する必要があるため、少し難しくなります。

class AggregateResult
{
    public object CallingObject;
    public Result Result;

    public static AggregateResult Create<T>(T t, Func<T,Result> func) 
    { 
        return new AggregateResult() { CallingObject = t, Result = func(t) }; 
    }
}
IEnumerable<AggregateResult> AggregateResults(Func<AggregateResult> func, params Func<AggregateResult>[] otherFuncs)
{
    yield return func();
    foreach (var otherFunc in otherFuncs)
        yield return otherFunc();
}
//Usage:
var results = AggregateResults(
            () => AggregateResult.Create(A, x=>x.Something()),
            () => AggregateResult.Create(B, x=>x.SomethingElse(3)),
            () => AggregateResult.Create(C, x=>x.SomethingOtherThing("apple")));
var failedResult = results.FirstOrDefault(x => x.Result.Failed);
if (failedResult != null) return new Status() { Failed = failedResult.CallingObject.GetType().ToString() };

そうは言っても、これは XY の問題のように聞こえるというコメントに同意します。

于 2013-08-19T17:02:23.783 に答える
0

次のように、成功した場合に null を返す Result の拡張メソッドを作成できます。

static class ResultExtension 
{
    public static Status GetStatus<T>(this Result res, T a) {
        return res.Failed? new Status{Failed=a.GetType().ToString()} : null;
    }
}

次に、 null 合体演算子 を使用して操作を連鎖できます??

return A.something().GetStatus(A)             ??
       B.somethingElse(3).GetStatus(B)        ??
       C.someOtherThing("apple").GetStatus(C) ??
       new Status{Failed=null, Success=true};

?? _ operator short-circuits、したがって、前の結果のいずれも null (つまり、失敗) でない場合にのみ、必要に応じて、すべての呼び出しが成功した場合にのみ、 somethingElse(3) または someOtherThing("apple") を評価します。成功ステータスを返します。

于 2013-08-19T17:24:29.363 に答える
0

最も簡単な方法は、 の新しいサブクラスを作成してプロパティをStatus埋めることです。コンストラクターに型として a を取り込ませ、そこで呼び出すことができます。FailedobjectGetType()

public class FailedStatus : Status
{
    public FailedStatus(object source)
    {
        this.Failed = source.GetType().ToString();
    }
}

Result resultA = A.something();
if(resultA.Failed) return new FailedStatus(A);

Result resultB = B.somethingElse(3);
if(resultB.Failed) return new FailedStatus(B);

Result result3 = C.someOtherThing("apple");
if(resultC.Failed) return new FailedStatus(C);

Resultから派生する場合Status、最も冗長でない方法は、変更、、something()およびsomethingElse(int)文字someOtherThing(string)列自体を設定することです(ただし、これが真の意味であるとは思えませんが、それは a ですが、ですResult.Failed)。boolStatus.Failedstring

于 2013-08-19T16:19:03.650 に答える