Policy Injection Application Block - ObjectBuilder - Dependency Injection
策略注入程序块 - ObjectBuilder-依赖注入
by David Hayden, Filed:
Enterprise Library 3.0
企业程序库 3.0
As I mentioned earlier, the February 2007 CTP of Enterprise Library 3.0 was released on Feb 28 and it introduces a new application block, the Policy Injection Application Block ( PIAB ).
我以前提到过,企业程序库 3.0 的2007年2月的 CTP版本在2月28日发布了,它包含一个新的应用程序块,策略注入应用程序块 ( PIAB) 。
As I understand it, the Policy Injection Application Block introduces AOP-like functionality into your winform and web applications by intercepting normal method calls and running handlers before and after method execution as defined by you through configuration.
当我了解它, 策略注入应用程序块通过拦截对方法的正常调用,在方法执行之前或之后根据定义好的配置,运行Handler进行引导,为你的程序引入AOP功能。
It does this by handing you a proxy class during factory creation that represents the class you asked for:
在factory创建你需要创建的指定类时传递给你一个代理类。
IOrder order = PolicyInjection.Create<Order, IOrder>();
IOrder order = PolicyInjection.Create<Order, IOrder>();
If there are policies defined in the configuration file that specify certain methods be intercepted on the Order Class, the statement above will return a proxy class that does method interception, otherwise it returns an instance of the Order Class.
如果在配置文件中有指定在Order类里哪些方法被拦截的规则定义,它返回一个进行方法拦截的代理类,否则返回Order类的一个实例。
The policy configuration information can be located in any configuration file and looks like this:
策略配置信息可以放在被指配件内,格式如下:
<policyInjection>
<policies>
<add name="Policy1">
<matchingRules>
<add name="MatchingRule1" />
<add name="MatchingRule2" />
</matchingRules>
<handlers>
<add name="Handler1" />
<add name="Handler2"/>
</handlers>
</add>
</policies>
</policyInjection>
Matching Rules tell the Policy Injection Application Block what methods to intercept and the handlers specify what happens before and / or after interception.
匹配规则告诉Policy Injection Application Block什么方法需要被拦截并且在handlers里的制动拦截发生在调用前还是调用后。
例子:
Let's say we have a policy for our store that whenever an order is returned it must be logged along with the reason it was returned.
假定我们的公司有这样一个规则:只要有订单被退回来,就必须连同被退回的理由一起做好记录。
For simplification, here are my classes:
下面是简化了的类别定义:
public class Order : IOrder
{
public void Return(string reason)
{
// Do something.
}
}
public interface IOrder
{
void Return(string reason);
}
One option is to use the Enterprise Library Logging Application Block directly and somewhere during the Return Process just make a call that logs the information:
一个选择是使用日志模块直接在换回处理过程中调用记录函数来记录信息。
LogEntry logEntry = new LogEntry();
logEntry.Message = ""
logEntry.Categories.Add("");
Logger.Write(logEntry);
With the Policy Injection Application Block, however, we can avoid this extra code by defining a policy that whenever a call is made to the Return Method on IOrder we should log a message.
通过Policy Injection Application Block,我们可以通过定义一个规则:无论合适只要调用Iorderd的Retern方法我们就记录这个消息,这样可以避免额外的编码工作。
There are numerous ways to match policies to methods, but in this case I am going to use the TagMatchingRule which means I just have to add a tag attribute to the Return Method on the Interface.
模块定义了多个匹配策略来过滤方法,但是在这个例子里,我将使TagMatchingRule,我需要在接口的return方法上添加一个标签属性。
Hence rather than writing all the LogEntry code above and explicitly calling the logging application block, I will just add the following to the IOrder Interface:
因此,不需要在所有调用的地方写logEntry代码快,只需要在Iorder接口处添加标签属性:
public interface IOrder
{
[Tag("Log")]
void Return(string reason);
}
I then define a Policy in my configuration file that says whenever [Tag("Log")] is on a method in my application ( as defined via my IOrder interface ), intercept the call and log information to the logging provider defined by the Logging Application Block:
然后,在配置文件内定义一个规则:无论何时,在这个应用程序中只要带[Tag(“Log”)]属性的方法被调用,就拦截调用日志程序块定义的提供者记录下信息。
<policyInjection>
<policies>
<add name="Logging">
<matchingRules>
<add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TagAttributeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection, Version=2.9.9.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" name="Tag Matching Rule" match="Log" ignoreCase="true" />
</matchingRules>
<handlers>
<add name="Logging Handler" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.LogCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers, Version=2.9.9.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
logBehavior="Before" beforeMessage="Before" includeParameterValues="true" includeCallTime="true" includeCallStack="false" severity="Information">
<categories>
<add name="General" />
</categories>
</add>
</handlers>
</add>
</policies>
</policyInjection>
There is a decent amount of configuration in there, but you won't normally have to look at it because you will be using the Graphical Configuration Tool that is integrated into Visual Studio for managing your Enterprise Library configurations.
可以使用配置工具来进行配置。
So when the following happens in my application:
当程序进行如下的调用时:
IOrder order = PolicyInjection.Create<Order, IOrder>();
order.Return("No change in size.");
The Policy Injection Application Block substitutes a proxy class for my Order Class because a policy is defined on the IOrder Interface:
应为有一个策略被定义在Iorder接口上,所以Policy Injection Application Block(返回)使用一个代理类来替代我的Order类
[Tag("Log")].
When the Return Method is called, the proxy class intercepts the call and runs the handlers in the order as defined in my configuration before and after calling the Return Method associated with the Order Class.
当Return方法被调用,这个代理类拦截调用并按照配置好的在调用Return方法之前或之后运行handlers。
In this case, it runs the LogCallHandler which logs information in the EventLog as I defined in the Logging Application Block Section ( but didn't show here for brevity ).
在这个例子里,它运行LogCallHandler。
What ends up in my EventLog is similar to the following but would realistically provide more useful information and be logged somewhere else:
大概会记录下边的信息:
Timestamp:
3/5/2007 9:12:17 PM
Message:
Before
Category:
General
Priority:
0
EventId:
1
Severity:
Information
Extended Properties:
reason -
No change in size.
Again, the code to do this logging is defined in policy and matched by an attribute.
全部代码
namespace LogMe
{
class Program
{
static void Main(string[] args)
{
IOrder order = PolicyInjection.Create<Order, IOrder>();
order.Return("No change in size.");
}
}
public class Order :IOrder
{
public void Return(string reason)
{
// Do something.
}
}
public interface IOrder
{
[Tag("Log")]
void Return(string reason);
}
}
A restriction worth mentioning is that in order for a method to be intercepted, the class in question must either inherit from MarshalByRefObject or implement an Interface.
有个限制是在Order里的方法要被被拦截,它必须继承MarshalByRefObject或实现一个接口。
As you can see, the Policy Injection Application Block is definitely cool and a nice addition to the Application Blocks.
这个程序块是个很酷并好使用的模块
But Where's My Dependency Injection?
但是在那儿体现依赖注入呢。
I love the new block, but have a bit of a concern.
我喜欢这个新的模块,但是还是有一点点担心
One of my concerns about the code above is this statement:
在代码上我注意到这样一个声明:
IOrder order = PolicyInjection.Create<Order, IOrder>();
Notice that I have to specify the concrete name of the class as well as the interface it implements.
它必须给出类别的具体名称和它实现的接口
I would like to have a Create Method like this:
我更喜欢有这样一个方法:
IOrder order = PolicyInjection.Create<IOrder>();
and via some Dependency Injection Container or better yet, Dependency Injection Application Block ( DIAB ), the Policy Injection Application Block just locate the concrete class ( or service really ) that goes with the interface.
通过一些依赖注入容器或更好的方法,依赖注入程序模块(DIAB),策略注入程序块仅仅查找伴随结构的类的关系(或真实服务?)
I mentioned this disappointment about no DI Container for use with ObjectBuilder in another post:
在另外一个帖子里我提到对、没有依赖注入容器使用ObjectBuilder而失望。
ObjectBuilder Dependency Injection Framework - Poor Undocumented Little Soul :)
So now as I mentioned in this CodePlex Discussion in the Enterprise Library Forums:
http://www.codeplex.com/entlib/Thread/View.aspx?ThreadId=7807
I have to use a Dependency Injection Tool alongside the Policy Injection Application Block even though ObjectBuilder plays a huge role in Enterprise Library.
我不得不使用新的依赖注入工具--Policy Injection Application Block,即使 ObjectBuilder 在企业程序库担有重要作用。
And, of course, most of the software factories, like the Web Client Software Factory that I have been giving presentations on at various Florida Code Camps, use their own containers, too, so I have to coordinate them with the PIAB.
并且,当然,绝大多数软件工厂,像Web Client Software Factory也使用他们自己的容器,因此我不得不使用PIAB来协调他们。
I am hoping if I keep harping on this I will either get what I want or somebody will educate me why Enterprise Library ( or Object Builder ) doesn't come with a Dependency Injection Application Block so all the applications that use Enterprise Library ( including ones built with the software factories ) don't have to use their own version.
没有使用objectbuilder是应为软件工厂等使用并扩展了ObjectBulder,这个aop是未了协调这个问题。
The Policy Injection Application Block could then hook into the Dependency Injection Application Block and give us wonderful capabilities.
Policy Injection Application Block能够后绑定?(连接?)Dependency Injection Application Block并带来奇妙的功能。
然后政策注入应用程序区块可以进入属国注入应用程序区块之内钩住而且给我们令人惊奇的能力。