接着Depandency Injection繼續。
最想做的還是用現成的程式子產品對程式進行行為注入。隻是不急,在此之前自己寫一個接口對象觀察一下IInterceptionBehavior接口的功效。
type LogingInterceptionBehavior() =
let WriteLog message =
printfn "From the logging interceptor: %A" message
interface IInterceptionBehavior with
member x.Invoke((input:IMethodInvocation), (getNext:GetNextInterceptionBehaviorDelegate)) =
String.Format("Invoke method {0}:{2} at {1}", input.MethodBase, DateTime.Now.ToLongTimeString(), input.Target) |> 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.target) |> WriteLog
| _ ->
String.Format("Method {0} threw exception {1} at {2}", input.MethodBase, result.Exception.Message, DateTime.Now.ToLongTimeString()) |> WriteLog
result
member x.GetRequiredInterfaces() =
Type.EmptyTypes |> Seq.ofArray
member x.WillExecute with get() = true
記錄日志是最常見的行為注入。
這裡最重要的是實作IIntercptionBehavior接口中的Invoke方法,這種方法有兩個參數。第一個是被攔截的接口,第二個則是一個托付行為清單(以托付的形式給出)。
這裡我們在清單循環前記錄參數,在循環後記錄傳回值。
let result = getNext.Invoke().Invoke(input, getNext)
這句代碼完畢詳細的工作。
攔截的行為是依次進行的,彼此之際并無聯系,也不應有聯系。每一個攔截都僅關注本身的詳細行為。這是最好的情況,隻是實際中也并不能保證這一點。對攔截的順序還是要多加注意。比方緩沖的樣例,有可能截斷注入行為清單。每一個行為對興許的動作不可控,是以當緩沖須要做一些特殊操作直接傳回值時,會忽略興許的動作。又比方權限管理。
container.AddNewExtension<Interception>() |> ignore
注冊
container.RegisterType<ITenantStore, TenantStore>(new Interceptor<TransparentProxyInterceptor>(),
new InterceptionBehavior<LogingInterceptionBehavior>())
let t = container.Resolve<ITenantStore>();
t.Msg()
能夠看到當解析接口時就會跳出非常多記錄。猜想應該在構造對象時做了不少的動作,父類的接口調用也會被記錄。
最後是結果
From the logging interceptor: "Invoke method Void Msg():FSI_0002+TenantStore at 11:59:00"
Hello, it's TenantStore
From the logging interceptor: "Method Void Msg() returned at 11:59:00"
假設我們重複調用RegisterType多次。記錄的條目也會對應增多。應該能夠想象結構上的變化。
以上。