首页 > 代码库 > 通过fsharp 使用Enterprise Library Unity 4 - Policy Interjection
通过fsharp 使用Enterprise Library Unity 4 - Policy Interjection
policy interception
Interception class拦截器还可以用Policy 以一种更高效的方式进行加载使用。拦截和被拦截对象的关系常见的是一对多,因为被拦截的主要是对象的方法所以有时数量巨大。Policy具有定义匹配模式的功能,所以可以简化这一匹配工作,不用一一添加被拦截对象。匹配的模式有
? Assembly name
? Namespace
? Type
? Tag attribute
? Custom attribute
? Member name
? Method signature
? Parameter type
? Property
? Return type
有时候在Interception class中也可进行一些过滤,这部分工作也可以移转到这里进行。我猜想这里的效率更高一些。不过两处目的不同,不可一概而论。
照例,显示被拦截对象
从代码中可以看到使用了PolicyInjectionBehavior指出Policy行为,打了一个行为桩。后续往容器中添加定义的CallHandler。模式匹配的定义也在这里。简单期间我选用了MemberNameMatchingRule,选中Msg方法。这里的方面名也可以加入*号作为通配符。
运行的结果和之前用InterceptionBehavior的方法的结果是一样的。比较感兴趣的是Order参数的行为,因为Fsharp在这里不是直接引用接口中的Order属性。这一层多余的层次会不会影响到顺序的表现呢?
我添加了一个CallHandler并切断了包括前一个接口实现时,往后续Pipe传递的通路。
随后在调用时增加一块,切换 order顺序
结果与设想一致。
以上
Interception class拦截器还可以用Policy 以一种更高效的方式进行加载使用。拦截和被拦截对象的关系常见的是一对多,因为被拦截的主要是对象的方法所以有时数量巨大。Policy具有定义匹配模式的功能,所以可以简化这一匹配工作,不用一一添加被拦截对象。匹配的模式有
? Assembly name
? Namespace
? Type
? Tag attribute
? Custom attribute
? Member name
? Method signature
? Parameter type
? Property
? Return type
有时候在Interception class中也可进行一些过滤,这部分工作也可以移转到这里进行。我猜想这里的效率更高一些。不过两处目的不同,不可一概而论。
照例,显示被拦截对象
open System open System.Collections open Microsoft.Practices.Unity open Microsoft.Practices.Unity.InterceptionExtension type ITenantStore = abstract member Msg : unit->unit type TenantStore() as x= //do printfn "new TenantStore %A" (x.GetHashCode()) abstract Msg : unit -> unit default x.Msg() = printfn "Hello, it's TenantStore" abstract Dispose : unit -> unit default x.Dispose() = printfn "TenantStore hase been cleaned" interface ITenantStore with member x.Msg() = x.Dispose() //测试Virtual Method中拦截内部方法的结果 x.Msg() interface IDisposable with member x.Dispose() = x.Dispose()声明实现ICallHandler接口的类。此处有一个地方需要注意。还是Fsharp语言的特性,无法隐式对接口进行转换。Fsharp的接口都是显示声明实现。如果不在类中暴露Order属性,在注册CallHandler的时候会提示缺少Order属性。好在ICallHandler接口比IInterceptionBehavior功能少,附加的点也就这一个。
type LoggingCallHandler() = let WriteLog message = printfn "From the logging interceptor: %A" message member val Order=0 with get,set interface ICallHandler with member x.Invoke((input:IMethodInvocation), (getNext:GetNextHandlerDelegate)) = String.Format("Invoke method {0}:{2} at {1}", input.MethodBase, DateTime.Now.ToLongTimeString(), input.MethodBase.DeclaringType) |> WriteLog let result = getNext.Invoke().Invoke(input, getNext) match result.Exception with | null -> String.Format("Method {0}:{3} returned {1} at {2}", input.MethodBase, result.ReturnValue, DateTime.Now.ToLongTimeString(), input.MethodBase.DeclaringType) |> WriteLog | _ -> String.Format("Method {0} threw exception {1} at {2}", input.MethodBase, result.Exception.Message, DateTime.Now.ToLongTimeString()) |> WriteLog result member x.Order with get()=x.Order and set(v) = x.Order <- v下面是具体的注册调用
using(new UnityContainer())(fun ctner-> ctner.AddNewExtension<Interception>() |> ignore ctner.RegisterType<ITenantStore, TenantStore>(new InterceptionBehavior<PolicyInjectionBehavior>(), new Interceptor<VirtualMethodInterceptor>()) |> ignore let first = new InjectionProperty("Order", 1) ctner.Configure<Interception>().AddPolicy("logging") .AddMatchingRule<MemberNameMatchingRule>(new InjectionConstructor([|"Msg"|], true)) .AddCallHandler<LoggingCallHandler>(new ContainerControlledLifetimeManager(), new InjectionConstructor(),first) |> ignore showregistrations ctner let t = ctner.Resolve<ITenantStore>() t.Msg() )
从代码中可以看到使用了PolicyInjectionBehavior指出Policy行为,打了一个行为桩。后续往容器中添加定义的CallHandler。模式匹配的定义也在这里。简单期间我选用了MemberNameMatchingRule,选中Msg方法。这里的方面名也可以加入*号作为通配符。
运行的结果和之前用InterceptionBehavior的方法的结果是一样的。比较感兴趣的是Order参数的行为,因为Fsharp在这里不是直接引用接口中的Order属性。这一层多余的层次会不会影响到顺序的表现呢?
我添加了一个CallHandler并切断了包括前一个接口实现时,往后续Pipe传递的通路。
type LoggingCallHandler() = let WriteLog message = printfn "From the logging interceptor: %A" message member val Order=0 with get,set interface ICallHandler with member x.Invoke((input:IMethodInvocation), (getNext:GetNextHandlerDelegate)) = String.Format("Invoke method {0}:{2} at {1}", input.MethodBase, DateTime.Now.ToLongTimeString(), input.MethodBase.DeclaringType) |> WriteLog let result = input.CreateMethodReturn(0) //break the pipe line //let result = getNext.Invoke().Invoke(input, getNext) match result.Exception with | null -> String.Format("Method {0}:{3} returned {1} at {2}", input.MethodBase, result.ReturnValue, DateTime.Now.ToLongTimeString(), input.MethodBase.DeclaringType) |> WriteLog | _ -> String.Format("Method {0} threw exception {1} at {2}", input.MethodBase, result.Exception.Message, DateTime.Now.ToLongTimeString()) |> WriteLog result member x.Order with get()=x.Order and set(v) = x.Order <- v type LoggingCallHandler2() = let WriteLog message = printfn "From the logging interceptor: %A" message member val Order=0 with get,set interface ICallHandler with member x.Invoke((input:IMethodInvocation), (getNext:GetNextHandlerDelegate)) = String.Format("Invoke method2 {0}:{2} at {1}", input.MethodBase, DateTime.Now.ToLongTimeString(), input.MethodBase.DeclaringType) |> WriteLog //let result = getNext.Invoke().Invoke(input, getNext) let result = input.CreateMethodReturn(0) //break the pipe line match result.Exception with | null -> String.Format("Method2 {0}:{3} returned {1} at {2}", input.MethodBase, result.ReturnValue, DateTime.Now.ToLongTimeString(), input.MethodBase.DeclaringType) |> WriteLog | _ -> String.Format("Method2 {0} threw exception {1} at {2}", input.MethodBase, result.Exception.Message, DateTime.Now.ToLongTimeString()) |> WriteLog result member x.Order with get()=x.Order and set(v) = x.Order <- v
随后在调用时增加一块,切换 order顺序
using(new UnityContainer())(fun ctner-> ctner.AddNewExtension<Interception>() |> ignore ctner.RegisterType<ITenantStore, TenantStore>(new InterceptionBehavior<PolicyInjectionBehavior>(), new Interceptor<VirtualMethodInterceptor>()) |> ignore let first = new InjectionProperty("Order", 1) let second = new InjectionProperty("Order", 2) ctner.Configure<Interception>().AddPolicy("logging") .AddMatchingRule<MemberNameMatchingRule>(new InjectionConstructor([|"Msg"|], true)) .AddCallHandler<LoggingCallHandler>(new ContainerControlledLifetimeManager(), new InjectionConstructor(),second) |> ignore ctner.Configure<Interception>().AddPolicy("logging2") .AddMatchingRule<MemberNameMatchingRule>(new InjectionConstructor([|"Msg"|], true)) .AddCallHandler<LoggingCallHandler2>(new ContainerControlledLifetimeManager(), new InjectionConstructor(),first) |> ignore showregistrations ctner let t = ctner.Resolve<ITenantStore>() t.Msg() )
结果与设想一致。
以上
通过fsharp 使用Enterprise Library Unity 4 - Policy Interjection
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。