デコレーター パターンは、元の実装を変更せずにその動作を拡張するものとして、特定のインターフェイスの基本実装を取得するメカニズムです。
基本クラスからの継承に似ていますが、より柔軟です。たとえば、デコレータ クラスは、同じインターフェイスを実装する他のクラスに適用できます。単一の基本クラスのみを拡張するという制限はありません。それらはまた、一緒に連鎖することもできます...
例えば
public interface IThing
{
void AMethod()
}
public abstract class ThingDecorator : IThing
{
private IThing inner;
public ThingDecorator(IThing inner)
{
this.inner = inner;
}
public virtual void AMethod()
{
this.inner.AMethod();
}
}
ThingDecorator から継承し、独自の拡張機能を仮想 AMethod に適用すると、渡された内部インスタンスに動作 (装飾) が追加されます。内部インスタンスはインターフェイスに結合されているため、そのインターフェイスの任意の実装にすることができます。
あなたの例では、AuditThingDecorator として ThingDecorator を継承し、base.AMethod() を呼び出す前に AMethod をオーバーライドして Audit 機能を含めることができます。
これは、単に属性をクラスに適用するのとは異なります。属性で動作を適用しようとしていると思います。属性は、コンテナ、またはそれらを読み取って実際に特定の動作を適用できるシステムの他の部分がある場合にのみ、クラスに動作を適用できます。DataAnnotations では、これらの属性を読み取って動作を適用する他のクラスがあります (たとえば、ASP.NET MVC 内では、DefaultModelBinder はいくつかの属性を使用して、モデルをバインドするときに検証を提供します)。
これは AOP (apsect 指向プログラミング) アプローチです。これを適用する 1 つの方法 (および私がよく使用する方法) は、Castle.Core を使用してインターセプターを作成し、自動的にインターフェイス メソッドを実装したり、仮想メソッドを拡張したり、インターセプトしているメソッド/プロパティから属性を読み取ったりして、動作を適用することです。
http://docs.castleproject.org/Tools.DynamicProxy-Introduction.ashx
どちらも本質的に特定のタイプのプロキシですが、上記の Decorator パターンは動的ではなく、コード内で作成され、AOP アプローチは実行時に動作を適用できます。