當然Unity架構中為我們提供了RegisterInstance,RegisterType方法我們可以在代碼中注冊到容器,比如NLayerApp中就在<code>IoCFactory中注冊一大堆抽象-具體關聯。但是在我們的實際實踐中一般會選擇另一種方式xml配置配置,因為這樣我們會得到更大的靈活性,需求變化隻要抽象接口不變,我們也隻需要在xml配置檔案中修改一行配置加入我們的具體實作,加入我們的程式集,就可以适應需求變化,這更滿足oo設計“開閉原則”。</code>
<code> 在這裡個人實踐利用抽象(接口)定義Attribute制定具體ConfigFile(配置檔案),Container(容器),Name(名稱)解決IOC植入,減少我們多次去讀取配置檔案。Unity為我們提供了在Web.config,App.config中配置注入資訊,或者注冊外部配置,但是很多時候我們更希望,在我們的 不同子產品下,應用不同的IOC配置資訊,這些可以減少維護的關聯少些,清晰,同時檔案夾的出現便于我們的配置資訊的管理。</code>
<code>Attribute實作:</code>
UnityInjectionAttributeView Code
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class UnityInjectionAttribute : Attribute
{
public UnityInjectionAttribute(string Container)
{
this.Container = Container;
}
public string Container
get;
set;
public string ConfigFile
public string Name
public Microsoft.Practices.Unity.Configuration.UnityConfigurationSection GetUnityConfigurationSection()
if (!string.IsNullOrEmpty(this.ConfigFile))
{
var fileMap = new System.Configuration.ExeConfigurationFileMap { ExeConfigFilename = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, this.ConfigFile) };
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, System.Configuration.ConfigurationUserLevel.None);
return configuration == null ? null : configuration.GetSection(Microsoft.Practices.Unity.Configuration.UnityConfigurationSection.SectionName) as Microsoft.Practices.Unity.Configuration.UnityConfigurationSection;
}
return System.Configuration.ConfigurationManager.GetSection(Microsoft.Practices.Unity.Configuration.UnityConfigurationSection.SectionName) as Microsoft.Practices.Unity.Configuration.UnityConfigurationSection;
}
複制代碼
在這裡我們GetUnityConfigurationSection根據ConfigFile擷取UnityConfigurationSection ,ConfigFile為空則目前應用配置檔案,不空則為路徑。在這裡我們為了性能,減少過多的IOC操作,讀取配置檔案,我們可以更具具體需要加入對配置檔案UnityConfigurationSection的緩存(ConfigFile作為key,UnityConfigurationSection為value )。
同時提供操作輔助方法:ELUnityUtility
View Code
public static class ELUnityUtility
public static T Resolve<T>() where T : class
return Resolve(typeof(T)) as T;
public static object Resolve(this Type type)
var attrs = type.GetCustomAttributes(typeof(Utils.UnityInjectionAttribute), true) as Utils.UnityInjectionAttribute[];
if (attrs != null && attrs.Length > 0)
var attr = attrs[0];
var unitySection = attr.GetUnityConfigurationSection();
if (unitySection != null)
{
var container = new Microsoft.Practices.Unity.UnityContainer().LoadConfiguration(unitySection, string.IsNullOrEmpty(attr.Container) ? unitySection.Containers.Default.Name : attr.Container);
var obj = string.IsNullOrEmpty(attr.Name) ? container.Resolve(type) : container.Resolve(type, attr.Name);
if (obj != null)
{
var piabAtttr = obj.GetType().GetCustomAttributes(typeof(ELPolicyinjectionAttribute), false) as ELPolicyinjectionAttribute[];
if (piabAtttr.Length > 0)
{
obj = Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.Wrap(type, obj);
}
return obj;
}
}
return null;
public static IEnumerable<T> ResolveAll<T>() where T : class
return ResolveAll(typeof(T)) as IEnumerable<T>;
public static object ResolveAll(this Type type)
return container.ResolveAll(type);
}
這裡我們就可以很簡便的擷取IOC翻轉。注:這裡還有根據具體實作是否具體ELPolicyinjectionAttribute來決定是否進行PIAB的AOP操作,當然我們也可以在Unity配置檔案中引入節點擴充
Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension,
Microsoft.Practices.Unity.Interception.Configuration
(PIAB利用的是透明代理速度較慢是以一般很少使用,當然你也可以實作具體的PIAB AOP方式比如注入MSIL,但我們已經有了很多注入MSIL的AOP架構了,我不準備去造輪子),ELPolicyinjectionAttribute:
[AttributeUsage(AttributeTargets.Class)]
public class ELPolicyinjectionAttribute : Attribute
這樣:我們的用戶端 就可以很簡單的使用了:
class Program
static void Main(string[] args)
ELUnityUtility.Resolve<IClass2>().Show();
(typeof(IClass2).Resolve() as IClass2).Show();
Console.Read();
public interface IClass1
void Show();
[Green.Utils.ELPolicyinjection]
public class Class1 : IClass1
#region IClass1 成員
[TestCallHandler]
public void Show()
Console.WriteLine(this.GetType());
#endregion
[Green.Utils.UnityInjection("First", Name = "class2", ConfigFile = "App1.config")]
public interface IClass2
public class Class2 : ConsoleApplication1.IClass2
[Microsoft.Practices.Unity.Dependency("class1")]
public IClass1 Class1
public void Show()
Class1.Show();
}
App1.Config配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity%22>
<container name="First">
<register type="ConsoleApplication1.IClass1,ConsoleApplication1" mapTo="ConsoleApplication1.Class1,ConsoleApplication1" name="class1" />
<register type="ConsoleApplication1.IClass2,ConsoleApplication1" mapTo="ConsoleApplication1.Class2,ConsoleApplication1" name="class2" />
</container>
</unity>
</configuration>
下邊是一個完整的帶PIAB的例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Green.Utils;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ELUnityUtility.Resolve<IClass2>().Show();
(typeof(IClass2).Resolve() as IClass2).Show();
Console.Read();
}
}
public interface IClass1
void Show();
[Green.Utils.ELPolicyinjection]
public class Class1 : IClass1
#region IClass1 成員
[TestCallHandler]
public void Show()
Console.WriteLine(this.GetType());
#endregion
[Green.Utils.UnityInjection("First", Name = "class2", ConfigFile = "App1.config")]
public interface IClass2
[Microsoft.Practices.Unity.Dependency("class1")]
public IClass1 Class1
get;
set;
Class1.Show();
[Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationElementType(typeof(CustomCallHandlerData))]
public class TestCallHandler : ICallHandler
#region ICallHandler 成員
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
if (input == null) throw new ArgumentNullException("input");
if (getNext == null) throw new ArgumentNullException("getNext");
Console.WriteLine("begin....");
var result = getNext()(input, getNext);
Console.WriteLine("end....");
return result;
public int Order
[AttributeUsage(AttributeTargets.Method)]
public class TestCallHandlerAttribute : HandlerAttribute
public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
return new TestCallHandler();
}
本文轉自 破狼 51CTO部落格,原文連結:http://blog.51cto.com/whitewolfblog/835199,如需轉載請自行聯系原作者