特性是一种类,继承自Attribute,提供一些特殊的信息,本身并没有价值,只有在动态编程利用反射的时候才会体现出强大。
1.1 特性的简单使用
这里自定义了TestInfoAttribute特性,修饰了Student类,能够通过student实例通过反射获取到原数据。在编译过程中会有.custom的自定义实例产生,那一串01 00 06…就是“Albert”。不破坏封装,AOP面向切面编程。
namespace AttributeExample {
class Program {
static void Main(string[] args) {
Student student = new Student() { Age = 24, ID = 1 };
Type type = student.GetType();
if (type.IsDefined(typeof(TestInfoAttribute), true)) {
TestInfoAttribute testInfoAttribute =(TestInfoAttribute) type.GetCustomAttribute(typeof(TestInfoAttribute));
testInfoAttribute.PrintTestInfo();
}
}
}
[TestInfo("Albert")]
public class Student {
public int ID { get; set; }
public int Age { get; set; }
}
[AttributeUsage(AttributeTargets.Class)]
public class TestInfoAttribute : Attribute {
private string _testInfo;
public TestInfoAttribute(string testInfo) {
_testInfo = testInfo;
}
public void PrintTestInfo() {
Console.WriteLine(_testInfo);
}
}
}
1.2 Student转换为StudentDTO几种方式
首先是硬编码的方式效率是最高的,但是没办法做成通用的方法,代码后期可维护性和扩展性变低。选择低一点的版本使用,不然可能找不到一些常用的方法。
- Json序列化、反序列化
- AutoMapper 类映射
- 静态字典缓存+表达式目录树
- 泛型缓存+表达式目录树 ```csharp using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AutoMapper; using System.Linq.Expressions; using DynamicExpresso; using Gremlin.Net.Process.Traversal;
namespace DTOExample {
class Program {
public static Dictionary
static void Main(string[] args) {
Student student = new Student() { Age = 24, ID = 1, Name = "Albert" };
//FirstMethod 使用Newtonsoft.Json序列号反序列化 此种方法效率很低
string sStudent = JsonConvert.SerializeObject(student); //先序列化为字符串
StudentDTO studentDTO = JsonConvert.DeserializeObject<StudentDTO>(sStudent);//反序列化
//SecondMethod 使用automapper映射 专属的类型映射工具,为ORM而生 效率高
Mapper.Initialize(x => x.CreateMap<Student, StudentDTO>());
StudentDTO studentDTO1 = Mapper.Map<Student, StudentDTO>(student);
//不同名称的映射
//Mapper.Initialize(config=> {
// config.CreateMap<Student, StudentDTO>().
// ForMember(dest => dest.DickName, options => options.MapFrom(sou => sou.Name));
//});
//StudentDTO studentDTO2 = Mapper.Map<Student, StudentDTO>(student);
//ThirdMethod 表达式目录树+静态缓存字典
//表达式目录树+静态字典
StudentDTO studentDTO3 = Trans<Student, StudentDTO>(student);
//效率较高,表达式目录树+泛型缓存
StudentDTO studentDTO4 = ExpressionGenericMapper<Student, StudentDTO>.Trans(student);
}
//表达式+静态字典
public static TOut Trans<TIn,TOut>(TIn tIn) {
TOut tOut = Activator.CreateInstance<TOut>();
string key = string.Format("funckey_{0}_{1}", tIn.GetType().Name, tOut.GetType().Name);
if (!_Dictionary.ContainsKey(key)) {
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
List<MemberBinding> memberBindingsList = new List<MemberBinding>();
foreach (var item in typeof(TOut).GetProperties()) {
MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingsList.Add(memberBinding);
}
foreach (var item in typeof(TOut).GetFields()) {
MemberExpression filed = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
MemberBinding memberBinding = Expression.Bind(item, filed);
memberBindingsList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingsList.ToArray());
Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
{
parameterExpression
});
Func<TIn, TOut> func = lambda.Compile();
_Dictionary[key] = func;
}
return ((Func<TIn, TOut>)_Dictionary[key]).Invoke(tIn);
}
}
class Student {
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public void PrintAge() {
Console.WriteLine(Age);
}
}
class StudentDTO {
public int ID { get; set; }
public string Name { get; set; }
//public string DickName { get; set; }
public int Age { get; set; }
public void PrintAge() {
Console.WriteLine(Age);
}
}
//表达式目录树+泛型缓存
public class ExpressionGenericMapper<TIn, TOut> {
private static Func<TIn, TOut> _FUNC = null;
static ExpressionGenericMapper() {
ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
List<MemberBinding> memberBindingsList = new List<MemberBinding>();
foreach (var item in typeof(TOut).GetProperties()) {
MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingsList.Add(memberBinding);
}
foreach (var item in typeof(TOut).GetFields()) {
MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
MemberBinding memberBinding = Expression.Bind(item, property);
memberBindingsList.Add(memberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingsList.ToArray());
Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
{
parameterExpression
});
_FUNC = lambda.Compile();//拼装是一次性的
}
public static TOut Trans(TIn tIn) {
return _FUNC(tIn);
}
}
}
<a name="JreM5"></a>
## 1.3 BS/CS开发 信息校验特性应用
BS-用户提交信息-页面JS检查-提交到后端-后端还得校验一下,前端不可信-入库<br />CS-用户提交信息-后端校验-入库
```csharp
namespace ExtendMethod {
class Program {
static void Main(string[] args) {
int a = 5;
int result = a.CalcAdd(5, 5);
UserModel userModel = new UserModel();
userModel.Account = "dfa";
bool valid1 = userModel.Validate<UserModel>(); //扩展方法
bool valid2 = AttributeExtend.Validate<UserModel>(userModel);
Console.WriteLine(result);
Console.WriteLine(valid1);
Console.WriteLine(valid2);
}
//public static string GetName<T>(this T t) where T : MemberInfo {
// if (t.IsDefined(typeof(T), true)) {
// }
//}
}
public static class Calc {
public static int CalcAdd(this int a, int b, int c) {
return a + b + c;
}
}
public static class AttributeExtend {
//一个方法完成不同类型的数据校验--泛型方法
//得想办法知道,要检查的实体有啥属性,属性有啥规则
//可以检查全部属性、可以为多个类型服务
public static bool Validate<T>(this T input) {
Type type = typeof(T);
foreach (var item in type.GetProperties()) {
if (item.IsDefined(typeof(AttributeBase), true)) {
object oValue = item.GetValue(input);
object[] oAttributeArray = item.GetCustomAttributes(typeof(AttributeBase), true);
foreach (AttributeBase attribute in oAttributeArray) {
if (attribute.Validate(oValue)) {
return false;
}
}
}
}
//foreach (var item in type.GetProperties()) {
// if (item.IsDefined(typeof(ElevenRequiredAttribute), true)) {
// object oValue = item.GetValue(input);//从input实例中获取属性值
// ElevenRequiredAttribute el = (ElevenRequiredAttribute)item.GetCustomAttribute(typeof(ElevenLengthAttribute), true);
// if (el.Validate()) {
// Console.WriteLine("不合法");
// return false;
// }
// }
// if (item.IsDefined(typeof(ElevenLengthAttribute), true)) {
// object oValue = item.GetValue(input);//从input实例中获取属性值
// //可以获取属性item上特性的实例
// ElevenLengthAttribute el = (ElevenLengthAttribute)item.GetCustomAttribute(typeof(ElevenLengthAttribute), true);
// if (el.Validate()) {
// Console.WriteLine("长度不对");
// return false;
// }
// }
//}
return true;
}
}
public class UserModel {
public string ShortName { get; set; }
[ElevenRequired]
[ElevenLength(10, 20)]
public string Account { get; set; }
public string Password { get; set; }
public string Email { get; set; }
}
/// <summary>
/// 校验属性的基类
/// </summary>
public abstract class AttributeBase : Attribute {
public abstract bool Validate(object oValue);
}
/// <summary>
/// 非空特性
/// </summary>
public class ElevenRequiredAttribute : AttributeBase {
public override bool Validate(object oValue) {
if (oValue == null || string.IsNullOrWhiteSpace(oValue.ToString())) {
Console.WriteLine("为空");
return false;
}
else
return true;
}
}
public class ElevenLengthAttribute : AttributeBase {
private int _Min = 0;
private int _Max = 0;
public ElevenLengthAttribute(int min, int max) {
_Min = min;
_Max = max;
}
public override bool Validate(object oValue) {
if (oValue.ToString().Length <= _Min && oValue.ToString().Length >= _Max) {
Console.WriteLine("长度不对");
return false;
}
else
return true;
}
}
}