服務定位模式(Service Locator Pattern)是一種軟件開發中的設計模式,經過應用強大的抽象層,可對涉及嘗試獲取一個服務的過程進行封裝。該模式使用一個稱爲"Service Locator"的中心註冊表來處理請求並返回處理特定任務所需的必要信息。html
某類ClassA依賴於服務ServiceA和服務ServiceB,服務的具體類型需在編譯時指定。web
這種條件下有如下缺點:設計模式
使用 Service Locator Pattern 來達成如下目標:app
建立一個 Service Locator,其包含各服務的引用,而且封裝了定位服務的邏輯。在類中使用 Service Locator 來獲取所需服務的實例。函數
Service Locator 模式並不描述如何實例化服務,其描述了一種註冊和定位服務的方式。一般狀況下,Service Locator 模式與工廠模式(Factory Pattern)和依賴注入模式(Dependency Injection Pattern)等結合使用。測試
服務定位器應該可以在不知道抽象類的具體類型的狀況下定位到服務。例如,它可能會使用字符串或服務接口類型來影射服務,這容許在無需修改類的條件下替換依賴項的具體實現。spa
一般 ServiceLocator 類提供 IServiceLocator 接口的實現單例,並負責管理該實例的建立和訪問。ServiceLocator 類提供 IServiceLocator 接口的默認實現,例如 ActivatingServiceLocator 類,能夠同時建立和定位服務。設計
在使用 Service Locator 模式以前,請考慮如下幾點:3d
Service Locator 的簡單實現,使用靜態類實現,未使用Singleton設計,僅做Mapping影射。版本控制
using System; using System.Collections.Generic; using System.Globalization; using System.Reflection; namespace Infrastructure { /// <summary> /// 服務定位器 /// </summary> public static class ServiceLocator { #region Fields private static readonly Dictionary<Type, Type> _mapping
= new Dictionary<Type, Type>(); private static readonly Dictionary<Type, object> _resources
= new Dictionary<Type, object>(); private static object _operationLock = new object(); #endregion #region Add /// <summary> /// 添加註冊資源 /// </summary> /// <typeparam name="TClass">資源類型</typeparam> /// <param name="instance">資源實例</param> public static void Add<TClass>(object instance) where TClass : class { Add(typeof(TClass), instance); } /// <summary> /// 添加註冊資源 /// </summary> /// <param name="typeOfInstance">資源類型</param> /// <param name="instance">資源實例</param> public static void Add(Type typeOfInstance, object instance) { if (typeOfInstance == null) throw new ArgumentNullException("typeOfInstance"); if (instance == null) throw new ArgumentNullException("instance"); if (!(typeOfInstance.IsInstanceOfType(instance))) { throw new InvalidCastException( string.Format(CultureInfo.InvariantCulture, "Resource does not implement supplied interface: {0}",
typeOfInstance.FullName)); } lock (_operationLock) { if (_resources.ContainsKey(typeOfInstance)) { throw new ArgumentException( string.Format(CultureInfo.InvariantCulture,
"Resource is already existing : {0}", typeOfInstance.FullName)); } _resources[typeOfInstance] = instance; } } #endregion #region Get /// <summary> /// 查找指定類型的資源實例 /// </summary> /// <typeparam name="TClass">資源類型</typeparam> /// <returns>資源實例</returns> public static TClass Get<TClass>() where TClass : class { return Get(typeof(TClass)) as TClass; } /// <summary> /// 查找指定類型的資源實例 /// </summary> /// <param name="typeOfInstance">The type of instance.</param> /// <returns>資源實例</returns> public static object Get(Type typeOfInstance) { if (typeOfInstance == null) throw new ArgumentNullException("typeOfInstance"); object resource; lock (_operationLock) { if (!_resources.TryGetValue(typeOfInstance, out resource)) { throw new ResourceNotFoundException(typeOfInstance.FullName); } } if (resource == null) { throw new ResourceNotInstantiatedException(typeOfInstance.FullName); } return resource; } /// <summary> /// 嘗試查找指定類型的資源實例 /// </summary> /// <typeparam name="TClass">資源類型</typeparam> /// <param name="resource">資源實例</param> /// <returns>是否存在指定資源類型的資源實例</returns> public static bool TryGet<TClass>(out TClass resource) where TClass : class { bool isFound = false; resource = null; object target; lock (_operationLock) { if (_resources.TryGetValue(typeof(TClass), out target)) { resource = target as TClass; isFound = true; } } return isFound; } #endregion #region Register /// <summary> /// 註冊類型 /// </summary> /// <typeparam name="TClass">實體類型,類型限制爲有公共無參構造函數</typeparam> public static void RegisterType<TClass>() where TClass : class, new() { lock (_operationLock) { _mapping[typeof(TClass)] = typeof(TClass); } } /// <summary> /// 註冊類型 /// </summary> /// <typeparam name="TFrom">資源類型</typeparam> /// <typeparam name="TTo">實體類型,類型限制爲有公共無參構造函數</typeparam> public static void RegisterType<TFrom, TTo>() where TFrom : class where TTo : TFrom, new() { lock (_operationLock) { _mapping[typeof(TFrom)] = typeof(TTo); _mapping[typeof(TTo)] = typeof(TTo); } } /// <summary> /// 是否已註冊此類型 /// </summary> /// <typeparam name="TClass">資源類型</typeparam> /// <returns>是否已註冊此類型</returns> public static bool IsRegistered<TClass>() { lock (_operationLock) { return _mapping.ContainsKey(typeof(TClass)); } } #endregion #region Resolve /// <summary> /// 獲取類型實例 /// </summary> /// <typeparam name="TClass">資源類型</typeparam> /// <returns>類型實例</returns> public static TClass Resolve<TClass>() where TClass : class { TClass resource = default(TClass); bool existing = TryGet<TClass>(out resource); if (!existing) { ConstructorInfo constructor = null; lock (_operationLock) { if (!_mapping.ContainsKey(typeof(TClass))) { throw new ResourceNotResolvedException( string.Format(CultureInfo.InvariantCulture,
"Cannot find the target type : {0}", typeof(TClass).FullName)); } Type concrete = _mapping[typeof(TClass)]; constructor = concrete.GetConstructor(
BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null); if (constructor == null) { throw new ResourceNotResolvedException( string.Format(CultureInfo.InvariantCulture,
"Public constructor is missing for type : {0}", typeof(TClass).FullName)); } } Add<TClass>((TClass)constructor.Invoke(null)); } return Get<TClass>(); } #endregion #region Remove /// <summary> /// 移除指定類型的資源實例 /// </summary> /// <typeparam name="TClass">資源類型</typeparam> public static void Remove<TClass>() { Teardown(typeof(TClass)); } /// <summary> /// 移除指定類型的資源實例 /// </summary> /// <param name="typeOfInstance">資源類型</param> public static void Remove(Type typeOfInstance) { if (typeOfInstance == null) throw new ArgumentNullException("typeOfInstance"); lock (_operationLock) { _resources.Remove(typeOfInstance); } } #endregion #region Teardown /// <summary> /// 拆除指定類型的資源實例及註冊映射類型 /// </summary> /// <typeparam name="TClass">資源類型</typeparam> public static void Teardown<TClass>() { Teardown(typeof(TClass)); } /// <summary> /// 拆除指定類型的資源實例及註冊映射類型 /// </summary> /// <param name="typeOfInstance">資源類型</param> public static void Teardown(Type typeOfInstance) { if (typeOfInstance == null) throw new ArgumentNullException("typeOfInstance"); lock (_operationLock) { _resources.Remove(typeOfInstance); _mapping.Remove(typeOfInstance); } } #endregion #region Clear /// <summary> /// 移除全部資源 /// </summary> public static void Clear() { lock (_operationLock) { _resources.Clear(); _mapping.Clear(); } } #endregion } }
using System; using Infrastructure; namespace ServiceLocatorTest { class Program { interface IServiceA { string GetData(); } class ServiceA : IServiceA { public string GetData() { return "This data is from ServiceA"; } } static void Main(string[] args) { ServiceLocator.RegisterType<IServiceA, ServiceA>(); IServiceA serviceA = ServiceLocator.Resolve<IServiceA>(); string data = serviceA.GetData(); Console.WriteLine(data); Console.ReadKey(); } } }