10

関数やメソッドの振る舞いを拡張pythonする実装が可能です。function decorators

特に、デバイス ライブラリを からpythonに移行していC#ます。デバイスとの通信でエラーが発生する可能性があり、カスタム例外で再発生する必要があります。

ではpython、次のように書きます。

@device_error_wrapper("Device A", "Error while setting output voltage.")   
def set_voltage(self, voltage):
    """
    Safely set the output voltage of device.
    """
    self.__handle.write(":source:voltage:level {0}".format(voltage))

このメソッド呼び出しは次のように展開されます

try:
    self.__handle.write(":source:voltage:level {0}".format(voltage))
except Error:
    raise DeviceError("Error while setting output voltage.", "DeviceA")

このパターンを使用するとtry-except、すべてのメソッドにすべての句を記述することなく、メソッドを簡単にラップおよび拡張できます。

を使用して同様のパターンを実装することは可能C#ですか?

デコレータ( device_error_wrapper)の実装が必要な場合はお申し付けください。

4

4 に答える 4

8

他の人が指摘しているように、PostSharp のようなツールを使用すると、コンパイル中に (実際には後で) 横断的なロジックを織り込むことができます。

別の方法は、実行時に行うことです。一部の IoC ツールでは、実装のプロキシ クラスに追加されるインターセプターを定義できます。これは実際よりもはるかに複雑に聞こえるので、Castle DynamicProxy に基づく例を示します。

まず、ラップする必要があるクラスを定義します。

[Interceptor(typeof(SecurityInterceptor))]
public class OrderManagementService : IOrderManagementService
{
    [RequiredPermission(Permissions.CanCreateOrder)]
    public virtual Guid CreateOrder(string orderCode)
    {   
        Order order = new Order(orderCode);
        order.Save(order); // ActiveRecord-like implementation
        return order.Id;
    }
} 

RequiredPermissionここではデコレータとして機能します。クラス自体はInterceptor、インターフェイス メソッド呼び出しのハンドラーを指定する属性で装飾されています。これは構成に入れることもできるため、クラスから隠されています。

インターセプターの実装には、デコレーターのロジックが含まれています

class SecurityInterceptor : IMethodInterceptor
{
    public object Intercept(IMethodInvocation invocation, params object[] args)
    {
        MethodInfo method = invocation.Method;
        if (method.IsDefined(typeof(RequiredPermission), true) // method has RequiredPermission attribute
            && GetRequiredPermission(method) != Context.Caller.Permission) {
            throw new SecurityException("No permission!");  
        }

        return invocation.Proceed(args);
    }

    private Permission GetRequiredPermission(MethodInfo method)
    {
         RequiredPermission attribute = (RequiredPermission)method.GetCustomAttributes(typeof(RequiredPermission), false)[0];
        return attribute.Permission;
    }
} 

ただし、いくつかの欠点があります。

  • DynamicProxy では、インターフェイスと仮想メソッドのみをラップできます。
  • 直接ではなく、IoC コンテナーを介してオブジェクトをインスタンス化する必要があります (既に IoC コンテナーを使用している場合は問題ありません)。
于 2013-03-11T16:35:12.733 に答える
5

Aspect Oriented Programmingを使用して同様のことを実現できます。過去にPostSharpしか使用したことがありませんが、商用利用は無料ではありません。

他にも AOP ソリューションがあり、Mono.Cecilを使用して同様のことを実現できますが、より多くの作業が必要になります。

Reza Ahmadi は、 C# と PostSharp を使用した Aspect Oriented Programmingという素敵な紹介記事を書きました。何を期待し、どのように機能するかについて十分に明確な考えを与えることができます。

于 2013-03-10T14:09:09.140 に答える
2

このようなデコレーターを C# で実装する簡単な方法はありません。カスタム属性は、デフォルトでは記述のみです。ただし、実際に使用できるように C# コンパイラまたはランタイムを拡張するプロジェクトがあります。一番いいのはPostSharpだと思います。これを使用すると、そのようなメソッド デコレータ (一般に「アスペクト」) を定義でき、必要に応じてコンパイル中にメソッドがラップされます。

クラスを実際にデコレータ クラスでラップすることでこれが実装されているのを見たこともありますが、それは大変な作業であり、本当に一般的な方法では実行できないと思います。ウィキペディアはデコレータパターンの記事でこれを示しています

于 2013-03-10T14:09:51.093 に答える
1

他の人が述べたように、AOP を探しています。PostSharp はコンパイル後の優れたソリューションですが、Castle DynamicProxyはランタイム AOP ソリューションです。

于 2013-03-10T14:37:01.783 に答える