C# Attribute
经常碰到使用Attribute的地方,但是基本没有自定义使用过,有时间稍稍学习理解下。
Attribute定义
Attribute本身是个类(Class),一个继承了System.Attribute的类。AttributeTargets枚举类型帮助确定Attribute适用对象。
[AttributeUsage(AttributeTargets.Property)]
public class RequiredAttribute : System.Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class MaxStringLengthAttribute : System.Attribute
{
public int MaxLength;
}
[AttributeUsage(AttributeTargets.Property)]
public class StandardWeightAttribute : System.Attribute
{
public int MinWeight;
public int MaxWeight;
public StandardWeightAttribute(int minWeight, int maxWeight)
{
MinWeight = minWeight;
MaxWeight = maxWeight;
}
}
[AttributeUsage(AttributeTargets.Class)]
public class ColorAttribute : System.Attribute
{
public FruitColor Color;
}
Attribute使用
可以在类,属性,方法等上方通过[Attribute(parameter…)]的方式引用Attribute。
有构造方法的可以通过构造方法给属性赋值,没有加入构造方法的public属性可以通过[Attribute(parameter1, parameter2=value,…)]的方式给属性赋值。
public class QualifiedFruit
{
[Required]
[MaxStringLength(MaxLength = 32)]
public string Name { get; set; }
public decimal Price { get; set; }
public virtual int Weight { get; set; }
public FruitColor Color { get; set; }
}
[Color(Color = FruitColor.YELLOW)]
public class QualifiedYellowKiWiFruit : QualifiedFruit
{
[StandardWeight(100, 120)]
public override int Weight { get => base.Weight; set => base.Weight = value; }
}
[Color(Color = FruitColor.GREEN)]
public class QualifiedGreenKiWiFruit : QualifiedFruit
{
[StandardWeight(120, 150)]
public override int Weight { get => base.Weight; set => base.Weight = value; }
}
public enum FruitColor
{
RED,
GREEN,
YELLOW
}
写个验证方法,或者扩展方法来验证Attribute。
Attribute基本通过反射的方式去获取。
public static class QualifiedFruitExt
{
public static bool IsStandard(this QualifiedFruit fruit)
{
var fruitType = fruit.GetType();
var attrs = fruitType.GetCustomAttributes(false);
// ColorType check
foreach(var attr in attrs)
{
if(attr.GetType().Name == typeof(ColorAttribute).Name)
{
var color = ((ColorAttribute)attr).Color;
if(color != fruit.Color)
{
return false;
}
}
}
// Name check
var propName = fruitType.GetProperty("Name");
var propNameAttrs = propName.GetCustomAttributes(true);
foreach(var attr in propNameAttrs)
{
if(attr.GetType().Name == typeof(RequiredAttribute).Name)
{
if (string.IsNullOrEmpty(fruit.Name))
{
return false;
}
}
if(attr.GetType().Name == typeof(MaxStringLengthAttribute).Name)
{
var maxLength = ((MaxStringLengthAttribute)attr).MaxLength;
if(!string.IsNullOrEmpty(fruit.Name) && fruit.Name.Length > maxLength)
{
return false;
}
}
}
// Weight check
var propWeight = fruitType.GetProperty("Weight");
var propWeightAttrs = propWeight.GetCustomAttributes(true);
foreach (var attr in propWeightAttrs)
{
if (attr.GetType().Name == typeof(StandardWeightAttribute).Name)
{
var min = ((StandardWeightAttribute)attr).MinWeight;
var max = ((StandardWeightAttribute)attr).MaxWeight;
if (fruit.Weight > max || fruit.Weight < min)
{
return false;
}
}
}
return true;
}
}
做一个简单的验证。
static void Main(string[] args)
{
QualifiedFruit fruit1 = new QualifiedGreenKiWiFruit
{
Name = "Super Delicious",
Price = 1000.00m,
Weight = 220,
Color = FruitColor.GREEN
};
var isStandard = fruit1.IsStandard();
}
Attribute使用场景
.Net MVC下面有不少Attribute的使用场景,像DataAnnotations,MVC库下的一些Attribute,还需要进一步学习。
问题
1.为什么使用Attribute?
找了些回答,大体意思是做第三方包的时候去用。这些工具包不关心你的业务逻辑,它们处理一些共通的东西,并且需要在运行时通过反射来做这些事。
不知道自己程序内部有哪些运用Attribute的好的场景。