首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在抽象属性类上指示AllowMultiple=false有什么意义?

在抽象属性类上指示AllowMultiple=false有什么意义?
EN

Stack Overflow用户
提问于 2010-04-15 21:23:57
回答 3查看 11.4K关注 0票数 19

在最近关于MVC属性的question上,有人询问在操作方法上使用HttpPost和HttpDelete属性是否会导致请求类型被允许或不允许请求(因为它不能同时是Post和Delete )。我注意到,ActionMethodSelectorAttribute ( HttpPostAttribute和HttpDeleteAttribute都是从它派生的)修饰为

代码语言:javascript
复制
[AttributeUsage(AttributeTargets.Method,
                AllowMultiple = false,
                Inherited = true)]

由于这一点,我原以为它不会同时允许HttpPost和HttpDelete在同一方法上,但是编译器不会抱怨。我有限的测试告诉我,基类上的属性使用被忽略了。AllowMultiple似乎只允许将两个相同的属性应用于方法/类,并且似乎没有考虑这些属性是否来自配置为不允许倍数的同一个类。此外,基类上的属性使用甚至不阻止您更改派生类上的属性用法。在这种情况下,甚至在基属性类上设置值有什么意义?这只是一种咨询,还是我在他们的工作中缺少了一些基本的东西?

FYI -事实证明,使用这两种方法基本上排除了该方法被考虑的可能性。属性是独立计算的,其中一个将始终表明该方法对请求无效,因为它不能同时是一个Post和一个Delete。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-04-29 13:47:05

在基本属性上设置AllowMultiple本质上设置了从它派生的所有属性的默认设置。如果希望从基属性派生的所有属性都允许多个实例,那么可以通过将[AttributeUsage]属性应用于基属性来保存复制,而不必对所有派生属性执行相同的操作。

例如,假设您希望允许这样做:

代码语言:javascript
复制
public abstract class MyAttributeBase : Attribute
{
}

public sealed class FooAttribute : MyAttributeBase
{
}

public sealed class BarAttribute : MyAttributeBase
{
}

[Foo]
[Foo]
[Bar]
[Bar]
public class A
{
}

目前,这会生成编译器错误,因为默认情况下,自定义属性不允许多个实例。现在,您可以将[AttribteUsage]应用于[Foo][Bar],如下所示:

代码语言:javascript
复制
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class FooAttribute : MyAttributeBase
{
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class BarAttribute : MyAttributeBase
{
}

但是,也可以将其应用于基本属性:

代码语言:javascript
复制
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public abstract class MyAttributeBase : Attribute
{
}

public sealed class FooAttribute : MyAttributeBase
{
}

public sealed class BarAttribute : MyAttributeBase
{
}

这两种方法具有相同的直接效果(允许[Foo][Bar]的多个实例),但第二种方法的间接效果是,来自[MyAttribute]的任何其他属性现在都将允许多个实例,除非它们有自己的[AttributeUsage]覆盖该设置。

票数 15
EN

Stack Overflow用户

发布于 2010-04-15 21:41:02

AllowMultiple允许/不允许多次使用特定属性。它不影响其他属性是否可以与其结合。

因此,例如,如果您有一个控制方法的重命名是否启用或禁用的ObfuscationAttribute,则不希望用户能够这样做:

代码语言:javascript
复制
[Obfuscation("DisableRenaming")]
[Obfuscation("EnableRenaming")]
void MyMethod()
{
}

在这种情况下,混淆不能同时启用和禁用,因此您可以使用AllowMultiple=false来确保该方法只使用此特定属性标记一次。

在相互排斥的情况下,您可以假设的是使用一个名为HttpSettings的属性,该属性使用一个副词,指示它是应用于Post还是删除“模式”。这样,AllowMultiple=false就可以强制执行期权的相互排他性。

票数 0
EN

Stack Overflow用户

发布于 2010-04-23 00:43:03

让我们做一个简短的测试:

代码语言:javascript
复制
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;

namespace TestAttrs {
    public abstract class BaseAttribute : Attribute { 
        public string text; 
    }

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class MultipleInheritedAttribute : BaseAttribute {  }

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
    public class MultipleNonInheritedAttribute : BaseAttribute {  }

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class SingleInheritedAttribute : BaseAttribute {  }

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class SingleNonInheritedAttribute : BaseAttribute {  }

    public class BaseClass {
        [MultipleInherited(text = "MultipleInheritedBase")]
        [MultipleNonInherited(text = "MultipleNonInheritedBase")]
        [SingleInherited(text = "SingleInheritedBase")]
        [SingleNonInherited(text = "SingleNonInheritedBase")]
        public virtual void Method() { ; }
    }

    public class DerivedClass : BaseClass {
        [MultipleInherited(text = "MultipleInheritedDerived")]
        [MultipleNonInherited(text = "MultipleNonInheritedDerived")]
        [SingleInherited(text = "SingleInheritedDerived")]
        [SingleNonInherited(text = "SingleNonInheritedDerived")]
        public override void Method() {
            base.Method();
        }
    }

    [TestClass]
    public class AttributesTest {
        [TestMethod]
        public void TestAttributes() {
            MemberInfo mi = typeof(DerivedClass).GetMember("Method")[0];
            object[] attrs = mi.GetCustomAttributes(true);

            string log = "";
            foreach(BaseAttribute attr in attrs) {
                log += attr.text+"|";
            }
            Assert.AreEqual("MultipleInheritedDerived|SingleInheritedDerived|SingleNonInheritedDerived|MultipleNonInheritedDerived|MultipleInheritedBase|", log);
        }
    }
}

如您所见,如果属性被标记为Inherted=true,那么派生类将返回属性,但是如果继承的方法被标记为相同的属性,则如果AllowMultiple=false,则会被抑制。因此-在我们的测试中,日志字符串包含"MultipleInheritedDerived“和"MultipleInheritedBase",但不包含"SingleInheritedBase”。

所以回答你的问题-有什么意义?这种组合允许您有一个带有虚拟方法的基控制器,您可以重写担心属性的wihout (它将从base方法中提取),但同时能够覆盖它(如果您愿意的话)。HttpPostAttribute不是一个很好的例子,因为它没有参数,但是其他属性可以从这些设置中受益。

此外,请注意代码消费属性:

代码语言:javascript
复制
       object[] attrs = mi.GetCustomAttributes(true);

指定它对继承的属性感兴趣。如果写

代码语言:javascript
复制
       object[] attrs = mi.GetCustomAttributes(false);

结果将包含4个属性,而不管它们的使用设置如何。因此,开发人员可以忽略继承的属性使用设置。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2649081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档