防止方法执行和属性以及变量访问/修改

时间:2012-11-06 05:19:00

标签: c# postsharp modularity aop

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

许多类将继承自A,可以是enableddisabled。考虑Bextends A。如果Bdisabled,我希望禁用所有方法执行和属性以及变量访问/修改。也就是说,如果B.ExecuteMethod();被禁用,B.Property = newValue;B将无效。此外,如果需要返回值,则如果0null,则该值将默认为Bdisabled。也就是说,我希望预期对象和值的默认值。

我正在使用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来引用A的{​​{1}}属性,这样Enabled只会OnEntry执行代码是真的。由于这是类级别的方面,因此我无法将Enabled的包装版本参数化为m_enabled,因为它超出了范围。

我是否有办法告诉ModularAttribute其所有者ModularAttribute具体implement?如果是,可以interface访问所述ModularAttribute的特定属性吗?如果是这样,这将解决我的问题。

为了澄清,我想“告诉”PostSharp:“使用interface的{​​{1}}保证class。所以,让ModularAttribute访问implement C ModularAttribute 1}}定义,因为它确保工作。“

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是解决这个问题的合适选择;但是,由于我对这种范式缺乏经验,我可能会以错误的方式接近它。

非常感谢任何指导。谢谢你的帮助,

1 个答案:

答案 0 :(得分: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");
    }
}