1

私はアスペクト指向プログラミングの経験がありません。ただし、PostSharpから入手できるPDFやドキュメントをかなり読んだことがあり、パラダイムの要点を理解していると思います。私にはかなり独特の問題があり、AOPを使用してそれを解決できると思います。私の苦境は次のとおりです。

多くのクラスはから継承します。Aこれはenabledまたはdisabledです。を考えBてみてくださいextends ABの場合disabled、すべてのメソッドの実行とプロパティ、および変数のアクセス/変更を無効にします。つまり、が無効になっている場合は効果がB.ExecuteMethod();ありB.Property = newValue;ませんB。さらに、戻り値が期待される場合、値はデフォルトで、0またはのnull場合Bはになりdisabledます。つまり、オブジェクトと値のデフォルト値を期待したいと思います。

私はPostSharpC#ライブラリを使用しています。これは非常に強力で十分に開発されているようです。私の問題は。によって解決できると信じていますAttributeInheritance。たとえば、次のAように定義できます。

[ModularAttribute(AttributeInheritance = MulticastInheritance.Multicast)]
public class A {

    private bool m_enabled;

    public A(){
        m_enabled = true;
    }

    public bool Enabled() {
        get {
            return m_enabled;
        }
        set {
            m_enabled = value;
        }
    }
}

Bできextend Aます。さらに、私の属性は次のModularAttributeように定義できます。

[Serializable]
public sealed class ModularAttribute : OnMethodBoundaryAspect {

    public ModularAttribute() {
    }

    public override void OnEntry(MethodExecutionArgs args) {
        // only execute code if enabled
    }
}

この属性はに適用されBますB extends A

私の問題の根本は次のとおりです。がtrueの場合にのみコードを実行するように、のプロパティModularAttributeを参照する必要があります。これはクラスレベルの側面であるため、スコープ外であるため 、ラップされたバージョンのtoをパラメーター化できません。AEnabledOnEntryEnabledm_enabledModularAttribute

ModularAttributeその所有者全員がimplement特定のものになると私が言うことができる方法はありinterfaceますか?もしそうなら、ModularAttribute上記から特定のプロパティにアクセスできますinterfaceか?もしそうなら、これは私の問題を解決するでしょう。

明確にするために、私はPostSharpに「class使用することModularAttributeが保証されている」と伝えたいと思いimplement Cます。したがって、確実に機能するため、定義されているものにModularAttributeアクセスできるようにします。C

C次のように定義できます。

public interface C { 
    public bool Enabled();
}

したがって、ではModularAttribute、私はの線に沿って何かをすることができます

if (attachedClass.Enabled == false) { 
    // don't execute code
} else {
    // execute code
}

この問題は、より一般的なユーザーごとのレベルではなく、オブジェクトごとのレベルでの認証として認識される可能性があります。if, elseすべてにチェックを追加する必要がPropertyあり、Methodそれextends Aは横断的関心事のようです。したがって、AOPはこの問題に適した選択肢だと思います。ただし、このパラダイムの経験が浅いため、間違った方法でアプローチしている可能性があります。

任意のガイダンスをいただければ幸いです。助けてくれてありがとう、

4

1 に答える 1

1

これだけの継承が設計上の欠陥か、少なくとも大きなメンテナンスの頭痛の種になるのではないかと少し心配していますが、そうではないと仮定して、兵士になりましょう...

あなたがやりたいことを正確に行う方法はないと思います。PostSharpに機能があったとしても、C#はコンパイル時に(PostSharpがそれに触れる前に)型を知る必要があります。

CompileTimeValidateを使用して、アスペクトが使用されているクラスが特定のタイプであることを確認することをお勧めします。それが配置されるとargs.Instance、無効なキャスト例外を気にせずにインターフェイスタイプにキャストできます。また、そのクラスが実装されていないIEnabled場合は、コンパイル時エラーが発生します。

簡単な例を次に示します。

public interface IEnabled
{
    bool Enabled { get; }
}

[Serializable]
public class ModularAttribute : OnMethodBoundaryAspect
{
    public override bool CompileTimeValidate(System.Reflection.MethodBase method)
    {
        if(typeof(IEnabled).IsAssignableFrom(method.DeclaringType))
            return true;
        Message.Write(method, SeverityType.Error, "MYERR001", "Aspect can't be used on a class that doesn't implement IEnabled");
        return false;
    }

    public override void OnEntry(MethodExecutionArgs args)
    {
        var obj = (IEnabled) args.Instance; // this will always be a safe cast
        if(!obj.Enabled)
            args.FlowBehavior = FlowBehavior.Return;
    }
}

ただし、落とし穴があります。このアスペクトをEnabledプロパティ自体で使用しないと、スタックオーバーフローが発生します(つまり、アスペクトがプロパティをチェックしたり、アスペクトがプロパティをチェックしたりするなど)。したがって、の使用は必ず除外 してください。EnabledAttributeExclude

class Program
{
    static void Main(string[] args)
    {
        var b = new B();
        b.Enabled = false;
        b.SomeMethod();
        b.AnotherMethod();
    }
}

public interface IEnabled
{
    bool Enabled { get; }
}

[Modular(AttributeInheritance = MulticastInheritance.Multicast)]
public class A : IEnabled
{
    [Modular(AttributeExclude = true)]
    public bool Enabled { get; set; }

    public void SomeMethod()
    {
        Console.WriteLine("in SomeMethod");
    }
}

public class B : A
{
    public void AnotherMethod()
    {
        Console.WriteLine("in AnotherMethod");
    }
}
于 2012-11-06T13:27:06.620 に答える