15

かなりあいまいなタイトルについてお詫びしますが、私が達成しようとしていることは、おそらくコードでより適切に述べられています。

WCFクライアントがあります。メソッドを呼び出すときは、各呼び出しをエラー処理コードでラップしたいと思います。そのため、メソッドを直接公開する代わりに、クライアントクラスで次のヘルパー関数を作成しました。

    public T HandleServiceCall<T>(Func<IApplicationService, T> serviceMethod)
    {
        try
        {
            return serviceMethod(decorator);
        }
        [...]
    }

そして、クライアントコードは次のようにそれを使用します:

service.HandleServiceCall(channel => channel.Ping("Hello"));

また、Pingの呼び出しは、エラーを処理しようとするロジックにうまくラップされます。

これは、サービスで実際に呼び出されているメソッドを知る必要があることを除いて、うまく機能します。当初は、使用しているエクスプレッションツリーを調べたいと思っていましFunc<IApplicationService, T>たが、それほど遠くはありませんでした。

最後に、デコレータパターンに落ち着きました。

    public T HandleServiceCall<T>(Func<IApplicationService, T> serviceMethod)
    {
        var decorator = new ServiceCallDecorator(client.ServiceChannel);
        try
        {
            return serviceMethod(decorator);
        }
        [...]
        finally
        {
            if (decorator.PingWasCalled)
            {
                Console.Writeline("I know that Ping was called")
            }
        }
    }

そしてデコレータ自体:

    private class ServiceCallDecorator : IApplicationService
    {
        private readonly IApplicationService service;

        public ServiceCallDecorator(IApplicationService service)
        {
            this.service = service;
            this.PingWasCalled = new Nullable<bool>();
        }

        public bool? PingWasCalled
        {
            get;
            private set;
        }

        public ServiceResponse<bool> Ping(string message)
        {
            PingWasCalled = true;
            return service.Ping(message);
        }
    }

それは本当に不格好で、かなり多くのコードです。これを行うためのよりエレガントな方法はありますか?

4

4 に答える 4

3

式を使用して、本体を検査することができます。

何かのようなもの

public T HandleServiceCall<T>(Expression<Func<IApplicationService, T>> serviceMethod)     
{         
    try         
    {          
        var func = serviceMethod.Compile();
        string body = serviceMethod.Body.ToString();
        return func(new ConcreteAppService()); 
    }        
    catch(Exception ex)
    {
        ...     
              }
}
于 2011-04-11T10:49:30.880 に答える
2

アスペクト指向アプローチの使用を検討しましたか?それはまさにあなたが必要としているもののように聞こえます。

ラッピング例外およびその他の「メタメソッド」機能は、serviceMethodsの機能に「直交する」アスペクトとして記述できます。

AOPに関するいくつかの一般的な情報:ウィキペディアのAOP

そして、コンテナを使用した潜在的なソリューション:WindsorCastleを使用したAOP

于 2011-04-11T10:36:23.190 に答える
1

式ツリーを使用した簡単な例を次に示します。

public T HandleServiceCall<T>(Expression<Func<T>> serviceMethod)
{
    try
    {
        return serviceMethod();
    }
    finally
    {
        var serviceMethodInfo = ((MethodCallExpression)serviceMethod.Body).Method;
        Console.WriteLine("The '{0}' service method was called", serviceMethodInfo.Name);
    }
}

この例では、serviceMethod式に常にメソッド呼び出しが含まれていることを前提としていることに注意してください。

関連リソース:

于 2011-04-11T10:45:57.237 に答える
0

はい、あなたのコードは過度に調理されていると思います。

プロキシを安全に破棄するためにコードをラップするという点では、ここで優れた実装を探してください。使い方は簡単です。

using (var client = new Proxy().Wrap()) {
 client.BaseObject.SomeMethod();
}

ここで、メソッド名にもアクセスする必要があります。そのためには、単に。を使用しますEnvironment.StackTrace。MarcGravellのスタックを上に歩くことを追加する必要がありますWrap

于 2011-04-11T11:06:01.517 に答える