提到特性,好多人都会疑惑特性(attribute),和注释有什么区别,简单来说,特性是给机器看的,而注释是给人看的。

特性不仅可以影响编译还可以影响运行,而注释只是为了让人更加容易理解、看懂代码而特别加注的解释而已。

那么怎么声明一个特性呢。

特性是一个继承或者间接继承Attribute的类
通常用attribute结尾,那么在使用的时候,可以去掉这个结尾

  public class TableAttribute : Attribute
{
private string _TableName = null; public TableAttribute(string tableName)
{
this._TableName = tableName;
} public string GetTableName()
{
return this._TableName;
}
}

我们还可以通过特性来约束特性,只需要在声明特性的代码上加约束代码

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]

AttributeTargers:约束特性使用范围;

AllowMultiple:是否允许多行

Inherited:是否允许继承

声明了特性后只需要在代码上加一行 [Table("User")]

   [Table("User")]
public class UserModel
{ public int Id { get; set; }
/// <summary>
/// 账户
/// </summary>
public string Account
{
set;
get;
}
/// <summary>
/// 密码
/// </summary>
public string Password
{
set;
get;
}
/// <summary>
/// EMaill
/// </summary>
public string Email
{
set;
get;
}
/// <summary>
/// 手机
/// </summary>
public string Mobile
{
set;
get;
}
}

后面需要做的就是获取到这个table名称。

 public static class Extend
{
public static string GetTable<T>(this T t) where T : new()
{
Type type = t.GetType();
object[] oAttribute = type.GetCustomAttributes(true);
foreach (var item in oAttribute)
{
if (item is TableAttribute)
{
TableAttribute attribute = item as TableAttribute;
return attribute.GetTableName();
}
}
return type.Name;
} }

最后调用。

 class Program
{
static void Main(string[] args)
{
string name = user.GetTableName<UserModel>()
}
}

特性除了可以添加一些额外信息外,还可以验证信息,

比如验证数据是否在一定的数值范围。

首先声明一个特性

 [AttributeUsage(AttributeTargets.Property)]
public class IntValidateAttribute : Attribute
{ private int _Min = 0;
private int _Max = 0; public IntValidateAttribute(int min, int max)
{
this._Min = min;
this._Max = max;
} public bool Validate(int num)
{
return num > this._Min && num < this._Max;
} }

然后在ID属性上加特性

   [IntValidateAttribute(0, 10000)]
public int Id { get; set; }  

这样就可以通过代码处理,达到验证并保存的目的。

 public static void Save<T>(T t)
{
bool isSafe = true; Type type = t.GetType(); foreach (var property in type.GetProperties())
{
object[] oAttributeList = property.GetCustomAttributes(true);
foreach (var item in oAttributeList)
{
if (item is IntValidateAttribute)
{
IntValidateAttribute attribute = item as IntValidateAttribute;
isSafe = attribute.Validate((int)property.GetValue(t));
}
}
if (!isSafe)
break;
} if (isSafe)
Console.WriteLine("保存到数据库");
else
Console.WriteLine("数据不合法");
}
UserModel user = new UserModel();   
BaseDAL.Save<UserModel>(user); 

特性就是在不改变类的情况下额外的增加信息。

这也是AOP编程的主要思想。

软件设计因为引入面向对象思想而逐渐变得丰富起来。“一切皆为对象”的精义,使得程序世界所要处理的逻辑简化,开发者可以用一组对象以及这些对象之间的关系将软件系统形象地表示出来。而从对象的定义,进而到模块,到组件的定义,利用面向对象思想的封装、继承、多态的思想,使得软件系统开发可以向搭建房屋那样,循序渐进,从砖石到楼层,进而到整幢大厦的建成。应用面向对象思想,在设计规模更大、逻辑更复杂的系统时,开发周期反而能变的更短。自然其中,需要应用到软件工程的开发定义、流程的过程控制,乃至于质量的缺陷管理。但从技术的细节来看,面向对象设计技术居功至伟。然而,面向对象设计的唯一问题是,它本质是静态的,封闭的,任何需求的细微变化都可能对开发进度造成重大影响。

在面向对象中,类的本质还是静态的,在我们声明了一个类后,在以后的修改维护中,随着需求的增加,其实我们还是不愿意去动已经写好的类。

比如说我们有个用户注册类

        public interface IUserProcessor
{
void RegUser(User user);
}
public class UserProcessor : IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine("用户已注册。Name:{0},PassWord:{1}", user.Name, user.Password);
}
}

但是后来我们希望在注册前和注册后都要来做一些事。这个时候 又不希望去动这个类,

在这里介绍一种设计模式,装饰器模式。用装饰器的模式去提供一个AOP功能

    public class UserProcessorDecorator : IUserProcessor
{
private IUserProcessor UserProcessor { get; set; }//声明一个接口类型变量
public UserProcessorDecorator(IUserProcessor userprocessor)
{
UserProcessor = userprocessor;//创建对象时,直接把对象赋值给变量
} public void RegUser(User user)
{
PreProceed(user);
try
{
this.UserProcessor.RegUser(user);
}
catch (Exception)
{ throw;
}
PostProceed(user);
} public void PreProceed(User user)
{
Console.WriteLine("方法执行前");
} public void PostProceed(User user)
{
Console.WriteLine("方法执行后");
}
}

装饰器模式实现静态代理
AOP 在方法前后增加自定义的方法

public static void Show()
{
User user = new User() { Name = "XiMa", Password = "1234567890" };
IUserProcessor processor = new UserProcessor();
processor = new UserProcessorDecorator(processor);//UserProcessor直接赋值给构造函数
processor.RegUser(user);
}

最后怎么通过Unity 实现动态代理

首先,通过NuGet加载Unity

在类文件中引用

using Microsoft.Practices.Unity.InterceptionExtension;//InterceptionExtension扩展
using Microsoft.Practices.Unity;
  public class UnityAOP
{
public static void Show()
{
User user = new User()
{
Name = "XiMa",
Password = "123123123123"
}; IUnityContainer container = new UnityContainer();//声明一个容器
container.RegisterType<IUserProcessor, UserProcessor>();//声明UnityContainer并注册IUserProcessor container.AddNewExtension<Interception>().Configure<Interception>()
.SetInterceptorFor<IUserProcessor>(new InterfaceInterceptor()); IUserProcessor userprocessor = container.Resolve<IUserProcessor>(); Console.WriteLine("********************");
userprocessor.RegUser(user);//调用
//userprocessor.GetUser(user);//调用
} #region 特性对应的行为
public class UserHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
User user = input.Inputs[0] as User;
if (user.Password.Length < 10)
{
return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10位"));
}
Console.WriteLine("参数检测无误"); IMethodReturn methodReturn = getNext.Invoke().Invoke(input, getNext); //Console.WriteLine("已完成操作"); return methodReturn;
}
} public class LogHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
User user = input.Inputs[0] as User;
string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password);
Console.WriteLine("日志已记录,Message:{0},Ctime:{1}", message, DateTime.Now);
return getNext()(input, getNext);
}
} public class ExceptionHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn methodReturn = getNext()(input, getNext);
if (methodReturn.Exception == null)
{
Console.WriteLine("无异常");
}
else
{
Console.WriteLine("异常:{0}", methodReturn.Exception.Message);
}
return methodReturn;
}
} public class AfterLogHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn methodReturn = getNext()(input, getNext);
User user = input.Inputs[0] as User;
string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password);
Console.WriteLine("完成日志,Message:{0},Ctime:{1},计算结果{2}", message, DateTime.Now, methodReturn.ReturnValue);
return methodReturn;
}
} public class BeforeLogHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {
IMethodReturn methodReturn = getNext()(input,getNext);
User user = input.Inputs[0] as User;
string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password);
Console.WriteLine("完成日志,Message:{0},Ctime:{1},计算结果{2}", message, DateTime.Now, methodReturn.ReturnValue);
return methodReturn;
}
} #endregion 特性对应的行为 #region 特性
public class UserHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
ICallHandler handler = new UserHandler() { Order = this.Order };
return handler;
}
} public class LogHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LogHandler() { Order = this.Order };
}
} public class ExceptionHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new ExceptionHandler() { Order = this.Order };
}
} public class AfterLogHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new AfterLogHandler() { Order = this.Order };
}
} public class BeforeLofHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new BeforeLogHandler() { Order=this.Order};
}
}
#endregion 特性 #region 业务
[UserHandlerAttribute(Order = 1)]
[ExceptionHandlerAttribute(Order = 3)]
[LogHandlerAttribute(Order = 2)]
[AfterLogHandlerAttribute(Order = 5)]
public interface IUserProcessor
{
void RegUser(User user); } public class UserProcessor : IUserProcessor//MarshalByRefObject,
{
public void RegUser(User user)
{
Console.WriteLine("用户已注册。"); }
}
#endregion 业务 /*
TransparentProxyInterceptor:直接在类的方法上进行标记,但是这个类必须继承MarshalByRefObject...不建议用
VirtualMethod:直接在类的方法上进行标记,但这个方法必须是虚方法(就是方法要带virtual关键字)
InterfaceInterceptor:在接口的方法上进行标记,这样继承这个接口的类里实现这个接口方法的方法就能被拦截
*/
}

因为Unity好多都是固定写法,没有什么原理,直接给文件,大家可以自己去调试,尝试一下。

 

Attribute(特性)与AOP的更多相关文章

  1. 如何在方法上贴上attribute(特性)捕捉方法的异常,来实现我们的需求

    在方法上贴上attribute(特性)捕捉方法的异常,其实这么做也是为了在项目中不会大量使用try-cacth这样的语句,同时使我们的代码看起来更简洁,更直观,将逻辑业务分离使得后期维护方便.这里我们 ...

  2. 【C#特性】 Attribute 特性

    msdn:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/attributes/creating-c ...

  3. .net学习之Attribute特性和EF关键知识点

    一.Attribute特性/标签1.Attribute用来对类.属性.方法等标注额外的信息,贴一个标签简单的说,定制特性Attribute,本质上就是一个类,它为目标元素提供关联附加信息,并在运行时以 ...

  4. [C#]Attribute特性(3)——AttributeUsage特性和特性标识符

    相关文章   [C#]Attribute特性 [C#]Attribute特性(2)——方法的特性及特性参数 AttributeUsage特性 除了可以定制自己的特性来注释常用的C#类型外,您可以用At ...

  5. [C#]Attribute特性(2)——方法的特性及特性参数

    上篇博文[C#]Attribute特性介绍了特性的定义,类的特性,字段的特性,这篇博文将介绍方法的特性及特性参数相关概念. 3.方法的特性 之所以将这部分单列出来进行讨论,是因为对方法的特性查询的反射 ...

  6. 关于C# 中的Attribute 特性

    关于C# 中的Attribute 特性 作者: 钢钢  来源: 博客园  发布时间: 2011-01-09 23:30  阅读: 13921 次  推荐: 12   原文链接 [收藏] 摘要:纠结地说 ...

  7. Attribute特性验证模型model

    数据验证我们往往分为前台验证和后台验证,而我们的后台验证每到一个方法中就要去验证一次,这样的代码想想都难以维护,这篇我们这篇文章就是为了解决这样的问题.用attribute 这个特性来解决这样的问题 ...

  8. .NET进阶篇03-Reflection反射、Attribute特性

    知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂 内容目录 一.概述二.反射1.反射使用2.创建对象3.调用方法4.字段属性三.特性四.总结 一.概述 反射其实无处不在,我们用VS进行调试时候, ...

  9. Net中Attribute特性的高级使用及自定义验证实现

    好久没写博客了,今天在百忙之中抽空来写篇文章,记录一下最近深入学习Attribute特性的笔记及心得.~~ 一.什么是特性? 特性(Attribute)是用于在运行时传递程序中各种元素(比如类.方法. ...

  10. C#基础系列——Attribute特性使用

    前言:上篇 C#基础系列——反射笔记 总结了下反射得基础用法,这章我们来看看C#的另一个基础技术——特性. 1.什么是特性:就博主的理解,特性就是在类的类名称.属性.方法等上面加一个标记,使这些类.属 ...

随机推荐

  1. SpringMvc支持跨域访问,Spring跨域访问,SpringMvc @CrossOrigin 跨域

    SpringMvc支持跨域访问,Spring跨域访问,SpringMvc @CrossOrigin 跨域 >>>>>>>>>>>> ...

  2. Android hook神器frida(一)

    运行环境 ● Python – latest 3.x is highly recommended ● Windows, macOS, or Linux安装方法使用命令 sudo pip install ...

  3. MySQL数据库“十宗罪”(十大经典错误案例)

    Top  1: Too many connections(连接数过多,导致连接不上数据库,业务无法正常进行) 问题还原 1 2 3 4 5 6 mysql> show variables lik ...

  4. [luogu P3801] 红色的幻想乡 [线段树][树状数组]

    题目背景 蕾米莉亚的红雾异变失败后,很不甘心. 题目描述 经过上次失败后,蕾米莉亚决定再次发动红雾异变,但为了防止被灵梦退治,她决定将红雾以奇怪的阵势释放. 我们将幻想乡看做是一个n*m的方格地区,一 ...

  5. ASP.NET Core API 版本控制

    几天前,我和我的朋友们使用 ASP.NET Core 开发了一个API ,使用的是GET方式,将一些数据返回到客户端 APP.我们在前端进行了分页,意味着我们将所有数据发送给客户端,然后进行一些dat ...

  6. (转)Linux下查看文件和文件夹大小 删除日志

    场景:在sts中执行自动部署时候maven提示No space left on device错误,后来经检查发现是磁盘空间满了,用下面的方法分析发现tomcat下面的logs目录占用了很大的空间,删除 ...

  7. html超级简单实现点赞(收藏)和取消赞效果

    1.前言 我们经常会遇到对一些列表呀进行点赞呀收藏数据等效果呀.今天就用html+css实现超级简单易上手的点赞和取消赞的demo展示. 2.详情 1.css样式 .like{ font-size:6 ...

  8. Android中的内容提供者

    Android中的内容提供者 为什么需要内容提供者 为了跨程序访问数据.试想如果在App-1中创建了一个私有数据库,App-2是不能直接访问的.因为权限不够,虽然可以使用chmod 777来修改权限, ...

  9. 简陋的 ASP.NET CORE 单页Web应用程序“框架”

    我对ASP.NET CORE了解不多,不知道是不是重复造轮子,也或者什么也不是,这个Demo是这样的: 1.非常简单或者说原始:2.将单页Web应用增加了一个页(Page)概念(相当于MVC的 Vie ...

  10. TASKCTL产品功能清单-转载

    功能分类 功能描述 一级 二级 关系 调度控制 作业依赖关系调度 作业依赖关系调度是调度最基本的功能,指作业间具有顺序的运行,比如:a.b.c三个作业,只有当a完成后才运行b,b完成才能运行c 作业并 ...