1

我对面向方面的编程没有经验。但是,我已经阅读了 PostSharp 提供的大量 PDF 和文档,并且我认为我理解了范式的要点。我有一个非常独特的问题,我相信 AOP 可以用来解决它。我的困境如下:

许多类将继承自A,可以是enableddisabled。考虑一下B,哪个extends A。如果Bdisabled,我希望禁用所有方法执行以及属性和变量访问/修改。也就是说,如果禁用B.ExecuteMethod();B.Property = newValue;则不会有任何影响。B此外,如果期望返回值,则该值将默认为0or nullif Bis disabled。也就是说,我希望对象和值具有预期的默认值。

我正在使用 PostSharp C# 库,它看起来非常强大且开发良好。我相信我的问题可以通过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.

我的问题的根源是:我需要ModularAttribute引用AEnabled属性,这样只有在为真OnEntry时才会执行代码。Enabled由于这是一个类级别的方面,因此我无法参数化 to 的包装版本,m_enabled因为ModularAttribute它超出了范围。

有没有办法让我知道ModularAttribute它的所有所有者都会implement有一个特定的interface? 如果是这样,可以ModularAttribute从所述访问特定属性interface吗?如果是这样,这将解决我的问题。

为了澄清,我想“告诉” PostSharp:“保证class使用的那个。所以,让访问任何定义,因为它可以确保工作。”ModularAttributeimplement CModularAttributeC

C可以定义为:

public interface C { 
    public bool Enabled();
}

因此,在 中ModularAttribute,我可以做一些类似的事情

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

这个问题可以被认为是每个对象级别的身份验证,而不是更典型的每个用户级别。必须对每一个都进行if, else检查PropertyMethodextends 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 属性本身上使用此方面,因为这会导致堆栈溢出(即方面检查属性,导致方面检查属性等)。所以一定要排除 Enabled使用AttributeExclude.

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 回答