C#--特性的运用试验
以下是学习笔记:
一,特性运用试验(一)
需求1:传统的代码
有这样一个用户状态的枚举类型:
namespace _015_特性.EnumExtend
{
/// <summary>
/// 枚举:用户的状态
/// </summary>
public enum UserState
{
/// <summary>
/// 正常
/// </summary>
Normal=0,
/// <summary>
/// 冻结
/// </summary>
Frozen=1,
/// <summary>
/// 删除
/// </summary>
Deleted=2
}
}
如果想要知道用户的状态,代码这样写:
UserState userState = UserState.Frozen;
if (userState == UserState.Normal)
{
Console.WriteLine("正常");
}
else if (userState == UserState.Frozen)
{
Console.WriteLine("冻结");
}
else if (userState == UserState.Deleted)
{
Console.WriteLine("删除");
}
上面的代码存在这样的问题:
如果状态要改变(正常,删除,冻结,,),改代码就非常的费劲,每次都要判断很多次
需求1:运用特性后的代码思路
【1】,先定义一个特性
namespace _015_特性.EnumExtend
{
//自定义Attribute,特性上还可以加特性
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
//参数1:可以被哪些情况下使用,如果是All就是被所有情况下都可以用。
//参数2:是否可以标记多个特性
//参数3:是否可以被继承
public class RemarkAttribute:Attribute
{
/// <summary>
/// 状态特性
/// </summary>
/// <param name="remark"></param>
public RemarkAttribute(string remark)
{
this.Remark = remark;
}
public string Remark { get;private set; }
}
}
【2】,特性定义好了之后,标记特性
namespace _015_特性.EnumExtend
{
/// <summary>
/// 枚举:用户的状态
/// </summary>
public enum UserState
{
/// <summary>
/// 正常
/// </summary>
[Remark("正常")]
Normal=0,
/// <summary>
/// 冻结
/// </summary>
[Remark("冻结")]
Frozen = 1,
/// <summary>
/// 删除
/// </summary>
[Remark("删除")]
Deleted = 2
}
}
【3】写一个调用特性方法的类
namespace _015_特性.EnumExtend
{
/// <summary>
/// 特性调用的类,用来调用特性的
/// </summary>
public class AttributeInvoke
{
public string GetRemark(UserState userState)
{
Type type = userState.GetType();//获取到传过来的类型
var fileId = type.GetField(userState.ToString());//根据参数这个值找到具体的字段
if(fileId.IsDefined(typeof(RemarkAttribute),true)) //查找字段有没有有定义RemarkAttribute这个特性,
{
RemarkAttribute remarkAttribute =
(RemarkAttribute) fileId.GetCustomAttribute(typeof(RemarkAttribute), true);
return remarkAttribute.Remark;//如果找到了,就返回这个特性的属性
}
else
{
return userState.ToString();//如果找不到,就返回传过来的这个值
}
}
}
}
【4】在主程序中调用
UserState userState2 = UserState.Frozen;
AttributeInvoke attributeInvoke=new AttributeInvoke();
Console.WriteLine(attributeInvoke.GetRemark(userState2));
改用特性的好处总结:不用if else的判断了,直接把userState2当做参数传入方法attributeInvoke.GetRemark(userState2)就可以啦。
总结上面的过程:定义特性--标记特性--调用(需要用到发射的技术)
二,特性运用试验(二),特性验证
【1】定义带特性的抽象类
namespace _015_特性.ValidateExtend
{
/// <summary>
/// 带有抽象方法的抽象类
/// </summary>
public abstract class AbstractValidateAttribute:Attribute
{
/// <summary>
/// 验证数据的方法
/// </summary>
/// <param name="objValue"></param>
/// <returns></returns>
public abstract bool Validate(object objValue);
}
}
【2】写三个实现抽象类的实现验证类
1,
namespace _015_特性.ValidateExtend
{
[AttributeUsage(AttributeTargets.Property)]
public class LongAttribute : AbstractValidateAttribute
{
private long _Long = 0;
public LongAttribute(long phoneLength)
{
this._Long = phoneLength;
}
/// <summary>
/// 检验手机号是否为11位
/// </summary>
/// <param name="objValue"></param>
/// <returns></returns>
public override bool Validate(object objValue)
{
return objValue != null && objValue.ToString().Length == 11;
}
}
}
2,
namespace _015_特性.ValidateExtend
{
public class RequriedAttribute : AbstractValidateAttribute
{
/// <summary>
/// 检验值是否为空
/// </summary>
/// <param name="objValue"></param>
/// <returns></returns>
public override bool Validate(object objValue)
{
return objValue != null && !string.IsNullOrWhiteSpace(objValue.ToString());
}
}
}
3,
namespace _015_特性.ValidateExtend
{
[AttributeUsage(AttributeTargets.Property)]
public class StringLengthAttribute : AbstractValidateAttribute
{
private int _Min = 0;
private int _Max = 0;
public StringLengthAttribute(int min,int max)
{
this._Min = min;
this._Max = max;
}
/// <summary>
/// 验证字符串的长度
/// </summary>
/// <param name="objValue"></param>
/// <returns></returns>
public override bool Validate(object objValue)
{
return objValue != null && objValue.ToString().Length >= this._Min && objValue.ToString().Length <= this._Max;
}
}
}
【3】,写一个调用方法的类
namespace _015_特性.ValidateExtend
{
public static class AttributeExtend
{
/// <summary>
/// 调用特性的方法的类(扩展方法)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static bool Validate<T>(this T t)
{
Type type = t.GetType();//找到t参数的类型
foreach (var property in type.GetProperties())//从类型里面查找遍历所有的属性
{
if (property.IsDefined(typeof(AbstractValidateAttribute), true)) //查找属性有没有被定义AbstractValidateAttribute特性
{
object objValue = property.GetValue(t);//获取属性的值
foreach (AbstractValidateAttribute attribute in property.GetCustomAttributes(typeof(AbstractValidateAttribute), true))
{
if (!attribute.Validate(objValue))//如果成功了以后就继续验证,否则就直接返回
{
return false;
}
}
}
}
return true;
}
}
}
【4】要验证的实体类,并标记特性
namespace _015_特性.ValidateExtend
{
public class Student
{
public int Id { get; set; }
[Requried]
[StringLength(5,10)]
public string StudentName { get; set; }
[Requried]
[Long(11)]
public long PhoneNumber { get; set; }
}
}
【5】在主程序中调用
Student student = new Student()
{
Id = 1,
PhoneNumber = 186684806622,
StudentName = "jason cai"
};
if (student.Validate())
{
Console.WriteLine("验证成功");
}
else
{
Console.WriteLine("验证失败");
}

浙公网安备 33010602011771号