在最近关于MVC属性的question上,有人询问在操作方法上使用HttpPost和HttpDelete属性是否会导致请求类型被允许或不允许请求(因为它不能同时是Post和Delete )。我注意到,ActionMethodSelectorAttribute ( HttpPostAttribute和HttpDeleteAttribute都是从它派生的)修饰为
[AttributeUsage(AttributeTargets.Method,
AllowMultiple = false,
Inherited = true)]由于这一点,我原以为它不会同时允许HttpPost和HttpDelete在同一方法上,但是编译器不会抱怨。我有限的测试告诉我,基类上的属性使用被忽略了。AllowMultiple似乎只允许将两个相同的属性应用于方法/类,并且似乎没有考虑这些属性是否来自配置为不允许倍数的同一个类。此外,基类上的属性使用甚至不阻止您更改派生类上的属性用法。在这种情况下,甚至在基属性类上设置值有什么意义?这只是一种咨询,还是我在他们的工作中缺少了一些基本的东西?
FYI -事实证明,使用这两种方法基本上排除了该方法被考虑的可能性。属性是独立计算的,其中一个将始终表明该方法对请求无效,因为它不能同时是一个Post和一个Delete。
发布于 2010-04-29 13:47:05
在基本属性上设置AllowMultiple本质上设置了从它派生的所有属性的默认设置。如果希望从基属性派生的所有属性都允许多个实例,那么可以通过将[AttributeUsage]属性应用于基属性来保存复制,而不必对所有派生属性执行相同的操作。
例如,假设您希望允许这样做:
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],如下所示:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class FooAttribute : MyAttributeBase
{
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class BarAttribute : MyAttributeBase
{
}但是,也可以将其应用于基本属性:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public abstract class MyAttributeBase : Attribute
{
}
public sealed class FooAttribute : MyAttributeBase
{
}
public sealed class BarAttribute : MyAttributeBase
{
}这两种方法具有相同的直接效果(允许[Foo]和[Bar]的多个实例),但第二种方法的间接效果是,来自[MyAttribute]的任何其他属性现在都将允许多个实例,除非它们有自己的[AttributeUsage]覆盖该设置。
发布于 2010-04-15 21:41:02
AllowMultiple允许/不允许多次使用特定属性。它不影响其他属性是否可以与其结合。
因此,例如,如果您有一个控制方法的重命名是否启用或禁用的ObfuscationAttribute,则不希望用户能够这样做:
[Obfuscation("DisableRenaming")]
[Obfuscation("EnableRenaming")]
void MyMethod()
{
}在这种情况下,混淆不能同时启用和禁用,因此您可以使用AllowMultiple=false来确保该方法只使用此特定属性标记一次。
在相互排斥的情况下,您可以假设的是使用一个名为HttpSettings的属性,该属性使用一个副词,指示它是应用于Post还是删除“模式”。这样,AllowMultiple=false就可以强制执行期权的相互排他性。
发布于 2010-04-23 00:43:03
让我们做一个简短的测试:
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不是一个很好的例子,因为它没有参数,但是其他属性可以从这些设置中受益。
此外,请注意代码消费属性:
object[] attrs = mi.GetCustomAttributes(true);指定它对继承的属性感兴趣。如果写
object[] attrs = mi.GetCustomAttributes(false);结果将包含4个属性,而不管它们的使用设置如何。因此,开发人员可以忽略继承的属性使用设置。
https://stackoverflow.com/questions/2649081
复制相似问题