代理对象(Proxy Object)会通过Handler链定位到真实对象(Real Object),而Policy则被注入到代理对象和真实对象中。整个流程如图:

我个人对Policy Injection Application Block使用的看法是:

用户先创建一个代理,用这个代理间接操作实体,在调用实体的方法或者成员属性时可以透明的触发一系列设置好的Handler(如日记记录,身份验证等),并且只需要修改相应的配置文件就能快速更改Handler链.(因为是个人看法,也许不太准确,官方解释在此 http://msdn.microsoft.com/en-us/library/ff647463.aspx)

Authorization横切关注点(Cross-Cutting Concerns)的处理方式如图所示:

PIAB目前预定义的Handler包括Validation Handler、Logging Handler、Exception Handling Handler、Authorization Handler、Caching Handler。这些Handler与Enterprise Library中的其他Application Block几乎是一一对应的。事实上,权限认证、日志、异常处理、缓存等,恰恰都是AOP技术最重要的关注点。在February 2007 CTP版本之前的Application Block,实际上已经具备了AOP的雏形。然后,由于它在“横切”与“注入”方面的缺乏,始终无法达到AOP所要求的重用目的。Policy Injection Application Block正好弥补了这样的缺憾。还是和以前一样,用实例来说话吧,因为这个模块功能较多,程序较大,在文章最后我也打包了供大家下载研究.

下面我们就来剖析Policy Injection Application Block:

首先分析一下需求:

1.建立一个财务管理器

2.提供有3个角色:

  a)  Teller:允许调用存款,取款,查账的方法

  b)  Assistant:允许调用查账方法

  c)  Janitor:无任何权限,做测试用

3. 创建几个用户,分配到这3个角色中,用户调用方法的代码中不用判断当前用户隶属于什么角色,即判断过程透明化

4.调用方法的信息以及错误信息自动写入日志,并且日记写入过程透明化

先说说按照传统的编程方法,我们假设有一个用户Charlie是属于Janitor角色的,当他按下程序中的查账按钮的时候应该被提示不允许,并把该错误写入日志中,则程序可能就会如下所示:

privatevoid button1_Click(object sender,EventArgs e)
{
//先进行角色验证
if(Charlie.所属角色 != Assistant ||Charlie.所属角色 != Teller)
{
//如果不符合条件,则报错并写入日志
MessageBox.Show("身份验证失败");
Log.Write("身份验证失败");
}
else
{
//获取余额
double balance = GetCurrentBalance();
MessageBox.Show(balance.ToString());
}
}

要注意的是,只有红色部分的代码真正实现了业务逻辑,而之前蓝色部分都是对身份的判断以及错误的处理,当你的程序出现越来越多类似的业务操作时,你会发现你需要大量拷贝此处的代码,这就已经说明你的程序需要重构了,试想一下,如果此时需要再多验证一个角色,或者要更换日志的处理方案时,你将需要重新将整个程序中出现相同业务逻辑的代码重新更新一次,这显然是不被允许的.于是Policy Injection Application Block此时就粉墨登场啦!

看看用了Policy Injection Application Block之后的代码风格:

privatevoid button1_Click(object sender,EventArgs e)
{
  try
   {
   double balance = GetCurrentBalance();
MessageBox.Show(balance.ToString());
  }
  catch (Exception ex)
   {
  MessageBox.Show(ex.Message);
   }
}

如何?简单吧,程序中只有关乎业务逻辑的代码,没有其他多余的非业务逻辑代码了,然而实现的功能是和之前的代码一样喔!想知道怎么实现的吗?请看下面的教程吧.(教程中的源代码我会打包提供给大家下载的,请在文章最后寻找下载链接)

1.首先我们需要一个BankAccount类,用于提供财务管理需要的属性以及方法,其中我们给这个类添加上一个balance私有属性用于表示余额.还提供了Deposit, Withdraw, GetCurrentBalance方法,实现存款,取款和查询余额的功能.该类的代码如下所示:

代码

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers;
using Microsoft.Practices.EnterpriseLibrary.Validation.PolicyInjection;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

namespace test
{
publicclass BankAccount : MarshalByRefObject
{
privatedecimal balance;
///<summary>
/// 获取当前余额
///</summary>
publicdecimal GetCurrentBalance()
{
return balance;
}

///<summary>
/// 存款
///</summary>
///<param name="depositAmount">存款金额</param>
[ValidationCallHandler]
publicvoid Deposit([RangeValidator(typeof(Decimal), "0.0", RangeBoundaryType.Exclusive, "0.0", RangeBoundaryType.Ignore, MessageTemplate ="存款金额必须大于零")]
decimal depositAmount)
{
balance += depositAmount;
}

///<summary>
/// 取款
///</summary>
///<param name="withdrawAmount">取款金额</param>
[ValidationCallHandler]
publicvoid Withdraw([RangeValidator(typeof(Decimal), "0.0", RangeBoundaryType.Exclusive, "1000.0", RangeBoundaryType.Inclusive, MessageTemplate ="取款金额必须介入0至1000之间.")]
decimal withdrawAmount)
{
if (withdrawAmount > balance)
{
thrownew ArithmeticException();
}
balance -= withdrawAmount;
}
}
}

2.运行EntLibConfig.exe, 选择Blocks菜单 ,单击Add Policy Injection Settings .点击Policies面板右上角的加号按钮AddPolicy,将Name属性修改为MyPoliy:

3.在Policies面板上右键Add Matching RulesAdd Member Name Matching Rule,点击创建好的MemberName Matching Rule面板上Member Names项目右侧的加号按钮,将BankAccount类中的成员方法名称(Deposit, Withdraw, GetCurrentBalance)添加进去,表示我们的MyPoliy决策中要对这些方法进行匹配,如果被程序调用或者出现错误异常,就会进行相应的处理.

4.于是,我们顺理成章的要添加一定的错误处理机制, 在Policies面板上右键—Add HandlersAdd Logging Call Handler,并设置为文本记载日志的方式,日志模块的详细介绍在此不多讲,大家可以参考我之前写的文章.至此,我们已经完成了成员方法被调用以及错误异常的处理机制了.日志文本格式化设置如下:

日志文本格式化

Timestamp:{timestamp}
Message:{message}
Category:{category}
Type:{property(TypeName)}
Method:{property(MethodName)}
Parameters:{dictionary({key} : {value})}
ReturnValue: {property(ReturnValue)}
Exception:{property(Exception)}
CallTime: {property(CallTime)}
Priority:{priority}
EventId:{eventid}
Severity:{severity}
Title:{title}
Machine:{machine}
ApplicationDomain: {appDomain}
ProcessId: {processId}
ProcessName: {processName}
Win32Thread Id: {win32ThreadId}
Thread Name: {threadName}

5.好,我们再看看需求,我们还需要创建3个角色和一些用户.在此就顺便讲解EL中的Application模块吧,因为它的功能很简单,就不专门做一个教程了,在此我们用它来配置角色和用户.选择Blocks菜单 ,单击Add Application Settings .点击Setting面板右上角的加号,添加一些用户,分别是

Key:   User:Alice       Value:Teller

Key:   User:Bob         Value:Assistant

Key:   User:Charlie   Value:Janitor

其中Key的值中User:为前缀,表示添加为用户,后面跟着的是用户名,而Value值表示该用户所隶属的角色,在程序中我们就可以写个函数从该模块中获取到用户名和角色啦(此处的用户名和角色一般是存储在数据库或者XML文件中,在此用Application模块完全是想借此机会讲解该模块而已,大家可以选用其他的方案):

6.好了,有了用户和角色,接下来要配置验证模块了.这就需要我们之前讲过的Security模块了,该模块的详细介绍在我之前的文章中已经写出,在此不多讲,只讲应用.

选择Blocks菜单 ,单击Add Security Settings .点击Authorization Providers面板右上角的加号按钮Add Authorization ProvidersAdd AuthorizationRule Provider. 

7.在Authorization Rule Provider面板上右键—AddAuthorization Rules,添加一个验证规则.在此我们设置3中验证规则,将 BankAccount类中的存款,取款,查账权限分别分配给刚刚建立的3个角色中,设置如下:

Name: Deposit                        Rule Expression: R:Teller

Name: Withdraw                    Rule Expression: R:Teller

Name: GetCurrentBalance    RuleExpression: R:Teller OR R:Assistant

8.设置好了验证规则模块,当然要想办法和我们的Poliy模块关联起来啦,因为是身份验证,所以匹配范围应该在整个Namespace,因此让我们回到Poliy模块, 点击Policies面板右上角的加号按钮Add Policy,将Name属性修改为Authorize,再在Authorize面板上右键Add Matching RulesAdd Namespace Matching Rule,并添加一个匹配对象,Name设置为test(请确保和你要匹配的Namespace名称相同):

9.在Authorizes面板上右键Add HandlersAdd Authorization Call Handler,属性设置如下图所示:

10.好了,至此我们也将验证规则模块和Poliy模块绑定起来了,下面可以运行程序进行验证了,程序已打包在下方可下载,我只是将演示效果截图给大家看看,详细内容请参看源代码:

再点击查看日志,会发现之前的操作都被记录下来了:

好了, PolicyInjection Application Block模块就讲到这,大家有什么好的想法可以给我留言~

下载源代码:

点击此处\(^  ^)/

转载于:https://www.cnblogs.com/huangcong/archive/2010/06/06/1752491.html

黄聪:Microsoft Enterprise Library 5.0 系列教程(九) Policy Injection Application Block相关推荐

  1. 黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block

    黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block 原文:黄聪:Microsoft Ent ...

  2. 黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级)

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级) 本章介绍的是企业库加密应用程序模块 ...

  3. 黄聪mysql_黄聪:Microsoft Enterprise Library 5.0 系列教程(五) Data Acc

    企业库数据库访问模块通过抽象工厂模式 , 允许用户通过简单的配置选择不同的数据库作为程序的数据源 , 大大解决了切换数据库时带来的麻烦 . 因为我本机只安装了 SQL Server 2005, 所以在 ...

  4. Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (初级)

    企业库加密应用程序模块提供了2种方式让用户保护自己的数据: Hashingproviders:  离散加密法, 简单来说就是把你的信息保存到内存中后用一个离散值表示并返回给程序,这样在程序中只能看到离 ...

  5. 黄聪:Microsoft Enterprise Library 5.0 系列教程(四) Logging Application Block

    企业库日志应用程序模块工作原理图:   从上图我们可以看清楚企业库日志应用程序模块的工作原理,其中LogFilter,Trace Source,Trace Listener,Log Formatter ...

  6. Microsoft Enterprise Library 5.0 系列(八) Unity Dependency Injection and Interception

    依赖注入容器Unity: Unity的构造类似于Castle中的IOC(控制反转 或者叫依赖注入)容器,我们使用抽象接口来隔离使用者和具体实现之间的依赖关系,但是不管再怎么抽象,最终还是要创建具体实现 ...

  7. Microsoft Enterprise Library 5.0 系列(五) Data Access Application Block

    企业库数据库访问模块通过抽象工厂模式,允许用户通过简单的配置选择不同的数据库作为程序的数据源,大大解决了切换数据库时带来的麻烦.因为我本机只安装了SQL Server 2005,所以在此只做SQL的演 ...

  8. Microsoft Enterprise Library 5.0 系列(二) Cryptography Application Block (初级)

    企业库加密应用程序模块提供了2种方式让用户保护自己的数据: Hashingproviders:  离散加密法, 简单来说就是把你的信息保存到内存中后用一个离散值表示并返回给程序,这样在程序中只能看到离 ...

  9. Microsoft Enterprise Library 5.0 系列(十) Configuration Application Block

    到目前为止,我们使用的模块都是在同一个配置文件中,这显然是不灵活的,我们希望每个功能模块能独立的在一个配置文件中体现,这样不仅易于管理,易于扩展,也易于阅读和分类.企业库当然考虑到了这个问题并且提供了 ...

最新文章

  1. python中的time库安装步骤-python中time库的实例使用方法
  2. 第十四章 springboot + profile(不同环境读取不同配置)
  3. LeetCode 2177. 找到和为给定整数的三个连续整数
  4. python 压缩字符串_python zlib - 压缩字符串的大小与香农熵
  5. 电子科大自考c语言试题,电子科大“立人班”40人全部读研深造
  6. 最近一段时间遇到的费了时间的问题
  7. java基础问题集锦一
  8. 前端-JavaScript1-6——JavaScript之变量类型的转换
  9. 《大象UML》看书笔记2:
  10. kdj指标详解曲线详解分析高位徘徊是什么KDJ指标详解曲线详解分析市场特征是什么
  11. pygame写简单推箱子游戏
  12. 基于JavaWeb医疗管理系统的开发与实现
  13. 中英文之间的空格处理
  14. pdf根据书签创建目录结构(方便查看各个主题的页码分布)pdf_xchange
  15. 【Java8新特性 串行/并行流-Optional容器类-时间格式化线程安全等】
  16. 安卓开发 java.lang.IllegalStateException isPlaying() 解决方案
  17. 如何远程公司 居家办公日渐常态 企业如何做好远程办公
  18. python通过Ctypes 模块 调用C++动态链接库,遇到的access violation reading 0x0000000000000000解决方案
  19. DataX实践趟坑大全
  20. 有源电场与无源磁场与麦克斯韦方程

热门文章

  1. SpringBoot第十五篇:Springboot整合RabbitMQ
  2. 蛰伏7年!他一天发表两篇Nature,还曾是曹原的师弟!
  3. 从校园情侣到教授夫妇,520当天他们携手发顶刊!
  4. 最喜欢随机森林?周志华团队 DF21 后,TensorFlow 开源决策森林库 TF-DF
  5. 海外博士一般朝九晚五,国内博士动辄十几个小时科研时间。为什么普遍认为海外博士水平比较高?...
  6. 最新!薪酬最高的大学专业公布!
  7. 清华大作业指导:一人单刷雨课堂需要多少工作量?快手工程师详解如何两周搞定...
  8. 不可错过的2019秋招CV岗心得!原来拿offer也是有套路的
  9. 你熟悉Git常用的命令吗?(点赞+收藏)
  10. golang实践LSM相关内容