【问题标题】:Prevent method execution and property and variable access/modification防止方法执行以及属性和变量访问/修改
【发布时间】:2012-11-06 21:27:06
【问题描述】:

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

许多类将继承自A,可以是enableddisabled。考虑B,其中extends A。如果Bdisabled,我希望禁用所有方法执行以及属性和变量访问/修改。也就是说,如果禁用了BB.ExecuteMethod();B.Property = newValue; 将不起作用。此外,如果期望返回值,则该值将默认为 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 引用AEnabled 属性,这样OnEntry 只会在Enabled 为真时执行代码。由于这是一个类级别的方面,我无法将 m_enabled 的包装版本参数化为 ModularAttribute,因为它超出了范围。

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

为了澄清,我想“告诉”PostSharp:“使用ModularAttributeclass 保证为implement C。因此,让ModularAttribute 访问C 定义的任何内容,因为它可以确保工作。 "

C可以定义为:

public interface C { 
    public bool Enabled();
}

因此,在ModularAttribute 中,我可以按照以下方式做一些事情

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

这个问题可以被认为是每个对象级别的身份验证,而不是更典型的每个用户级别。必须对每个PropertyMethod 添加if, else 检查extends A 似乎是一个跨领域的问题。因此,我认为 AOP 是解决这个问题的合适选择;但是,由于我对这种范式缺乏经验,我可能会以错误的方式接近它。

任何指导将不胜感激。感谢您的帮助,

【问题讨论】:

  • 嗨,我想澄清一些疑问。为什么不使用 [Transaction(AttributeInheritance=MulticastInheritance.MultiCast)] 还是因为 Modular Attribute 是方法级别的方面?

标签: c# postsharp modularity aop


【解决方案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");
    }
}

【讨论】:

  • 非常感谢您的帮助!如果您的建议解决了问题,或者我遇到了进一步的问题,我会告诉您。再次感谢您的帮助 - 非常感谢。
  • 您的解决方案非常有效。感谢所有的帮助。
  • 对于那些想知道的人,我在A 上应用了第二个AttributeSecondAttribute : LocationInterceptionAspect,这样它可以防止propertymember variableA 被禁用时访问/修改。这可以通过overridingOnGetValueOnSetValue 完成。就像上面一样,需要排除存在于SecondAttribute 中的任何boolean 变量,这些变量驻留在A 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-03
  • 1970-01-01
相关资源
最近更新 更多