【问题标题】:C# attribute that can only be on a method within a class with another attribute只能在具有另一个属性的类中的方法上的 C# 属性
【发布时间】:2016-06-09 02:29:18
【问题描述】:

在 C# 中是否可以对属性进行限制,使其只能在具有另一个属性的类中的方法上?

[MyClassAttribute]
class Foo
{
    [MyMethodAttribute]
    public string Bar()
}

其中“MyMethodAttribute”只能在具有“MyClassAttribute”的类中。

这可能吗?如果可以,怎么做?

【问题讨论】:

  • 我怀疑这是可能的,属性本身什么都不做。
  • 我不知道实现这一点的编译时方法。但是,在 MyMethodAttribute ctor 中,您可以通过反射检查托管 MyMethodAttribute 的类上是否存在必需的属性。
  • 您可以编写一个 Roslyn 分析器,在编译时对此进行验证,如果违反此规则则显示错误。

标签: c# attributes restriction


【解决方案1】:

如果您要尝试对方法属性进行运行时验证,您可以执行以下操作:

public abstract class ValidatableMethodAttribute : Attribute
{
    public abstract bool IsValid();
}

public class MyMethodAtt : ValidatableMethodAttribute
{
    private readonly Type _type;

    public override bool IsValid()
    {
        // Validate your class attribute type here
        return _type == typeof (MyMethodAtt);
    }

    public MyMethodAtt(Type type)
    {
        _type = type;
    }
}

[MyClassAtt]
public class Mine
{
    // This is the downside in my opinion,
    // must give compile-time type of containing class here.
    [MyMethodAtt(typeof(MyClassAtt))]
    public void MethodOne()
    {

    }
}

然后使用反射找到系统中所有的ValidatableMethodAttributes,并在它们上调用IsValid()。这不是很可靠并且相当脆弱,但是这种类型的验证可以实现您所寻找的。​​p>

或者传递类的类型(Mine),然后在IsValid() 中使用反射查找Mine 类型上的所有属性。

【讨论】:

    【解决方案2】:

    你也许可以用 PostSharp 做到这一点:(see: Compile time Validation in this tutorial)

    然后在您的属性中,将使用类似以下代码检查父类:

    public class MyCustomAttribute : Attribute
    {
        public MyCustomAttribute()
        {
            if (GetType().CustomAttributes.Count(attr => attr.AttributeType == typeof (MyCustomClassAttribute)) < 1) 
            {
                 throw new Exception("Needs parent attribute") //Insert Postsharp method of raising compile time error here
            }
    

    【讨论】:

      【解决方案3】:

      您不能对用户定义的属性执行此操作。但是我相信编译器有这样的机制,内置的FieldOffsetAttribute就是用这个的。

      struct MyStruct
      {
          [FieldOffset(1)]    //compile error, StructLayoutAttribute is required
          private int _num;
      }
      

      编辑我认为如果你注入构建过程是可行的,使用类似PostSharp的东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-17
        • 2021-04-14
        • 2020-03-05
        • 2014-01-13
        • 1970-01-01
        • 1970-01-01
        • 2019-09-05
        • 2013-12-12
        相关资源
        最近更新 更多