AOP---Unity使用初探
.Net下面實現(xiàn)依賴注入的框架有很多,如Spring.Net等等。微軟也有自己的工具---Unity。作為企業(yè)庫的一部分,Unity實現(xiàn)依賴注入也成為學習企業(yè)庫比較重要的一環(huán)。微軟給出的說法是【它是一個輕量級的、可擴展的依賴注入容器】。
對Unity高級用法,我還不是很熟悉,一下就簡單說說它的初級用法,給初學者掃掃盲,高手就可以直接跳過了。如果我理解有誤,還希望大鳥們不理賜教。
首先介紹一下開發(fā)環(huán)境:Visio Studio2008 Team,SP1、企業(yè)庫版本5.0。
提到Unity,就不能不說UnityContainer。UnityContainer是Unity中最基礎的類,它是實現(xiàn)依賴注入的基礎。 這里我只給出一種最基本的攔截方式------UnityContainer對象中RegisterType、Resolve實現(xiàn)。RegisterType從函數(shù)名上理解就是注冊類型之間的關系。Resolve:通過UnityContainer對象獲取注冊的對象。被攔截的對象需要實現(xiàn)IInterceptionBehavior接口。
總體上,實現(xiàn)攔截有兩個步驟:
1、注冊被攔截對象
2、獲取被攔截對象的實例。
當然,以上兩步都是通過UnityContainer來實現(xiàn)的。也可以通過配置的方式來實現(xiàn)。這里先熟悉一下通過編程的方式來進行配置的應用,通過配置的方式實現(xiàn),留待之后介紹構(gòu)造函數(shù)注入、屬性、方法注入的時候再進行介紹。
先簡要介紹一下本節(jié)示例中類、接口之間的關系。人員接口IPerson、學生類Student,Student實現(xiàn)IPerson。我們需要攔截Student類中實現(xiàn)的IPerson接口中的方法【一個為虛方法、一個為實例方法】并在攔截的所執(zhí)行的目標方法執(zhí)行進行一些輸出操作。實現(xiàn)攔截得到類ILogInterception、ILogInterception1,需要實現(xiàn)企業(yè)庫接口-----IInterceptionBehavior。代碼如下:
public interface IPerson
{
string Name { get; set; }
int Age { get; set; }
void Speek();
void Run(int speed);
}
public class Student : IPerson
{
public string Name { get; set; }
public int Age { get; set; }
public virtual void Speek()
{
Name = "tesetName";
Age = 29;
Console.WriteLine("Person Speeks");
}
public void Run(int speed)
{
Console.WriteLine(string.Format("Student Runs... at speed {0}", speed));
}
}
public class LogInterception : IInterceptionBehavior
{
private static readonly MethodInfo methodInfo =
typeof(Student).GetMethod("Speek");
public IEnumerable<Type> GetRequiredInterfaces()
{
return new[] { typeof(IPerson) };
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("開始攔截");
if (input == null)
{
throw new Exception("參數(shù)不能為null");
}
if (getNext == null)
{
throw new Exception("委托不能為null");
}
if (input.MethodBase == methodInfo)
{
Console.WriteLine("開始執(zhí)行目標方法");
return getNext()(input, getNext);
}
else
{
return input.CreateMethodReturn(null);
}
}
public bool WillExecute
{
get { return true; }
}
}
public class ILogInterception1 : IInterceptionBehavior
{
private static readonly MethodInfo methodInfo =
typeof(IPerson).GetMethod("Run");
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return new[] { typeof(IPerson) };
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("開始攔截");
if (input == null)
{
throw new Exception("參數(shù)不能為空");
}
if (getNext == null)
{
throw new Exception("委托沒有被實例化");
}
if (input.MethodBase == methodInfo)
{
Console.WriteLine("即將執(zhí)行目標方法");
Console.WriteLine(string.Format("目標方法參數(shù)個數(shù)為:{0}",input.Arguments.Count));
if (input.Arguments.Count > 0)
{
Console.WriteLine(string.Format("實際參數(shù)為:{0}", input.Arguments[0]));
}
InvokeInterceptionBehaviorDelegate tempDelegate = getNext();
return tempDelegate(input, getNext);
}
else
{
return input.CreateMethodReturn(null);
}
}
}
在攔截虛方法的使用代碼如下:
container.AddNewExtension<Interception>();
container.RegisterType<Student>(
new Interceptor<VirtualMethodInterceptor>(),
new InterceptionBehavior<LogInterception>(),
new AdditionalInterface<IPerson>());
var studentInfo = container.Resolve<Student>();
studentInfo.Speek();
輸出如下圖:

由以上輸出結(jié)果可知:studentInfo在調(diào)用Speek方法時,首先不是直接去調(diào)用Student類的Speed方法,而是執(zhí)行了LogInterception類中的Invoke方法。在Invoke方法getNext()(input, getNext)中,才真正調(diào)用了Student類的Speed方法。這就是我們所說的攔截。
以上是對接口中的虛方法中的攔截方式。對實例方法的攔截方式和上述攔截又有所不同。實例方法的攔截方式如下:
container.AddNewExtension<Interception>();
container.RegisterType<IPerson,Student>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<ILogInterception1>()
);
var student = container.Resolve<IPerson>();
student.Run(100);
輸出如下圖:

注意:攔截虛方法和攔截實例方式的方式是不一樣的。如果用攔截實例的方式來攔截虛方法或者用攔截虛方法的方式來攔截實例方法,則不會有對我們需要進行攔截的方法進行攔截。
此外,一種寫法在我看攔截的時候有點費解,就是getNext()(input, getNext);因為在我們的編程習慣里,什么時候會有一個方法會有這種調(diào)用方式呢。?這里就需要好好考慮考慮了。getNext只是一個簡單的方法簽名嗎。?實際上它是GetNextInterceptionBehaviorDelegate類型的。從其名字上看便可知它是一個委托類型,可是委托也沒有像這樣使用的。再看看GetNextInterceptionBehaviorDelegate的定義:
public delegate InvokeInterceptionBehaviorDelegate GetNextInterceptionBehaviorDelegate();
從GetNextInterceptionBehaviorDelegate的簽名便知道它的返回值InvokeInterceptionBehaviorDelegate應該也是一種委托類型的,如果是這樣那也不足為怪了。驗證一下這個想法,看看InvokeInterceptionBehaviorDelegate的定義:
public delegate IMethodReturn InvokeInterceptionBehaviorDelegate(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext);
確實,它是一個需要IMethodInvocation、與GetNextInterceptionBehaviorDelegate類型的委托。
浙公網(wǎng)安備 33010602011771號