IoC是個好東西,但是為了這個功能而使用類似 Castle 這種大型框架的話,感覺還是不大好
代碼是之前寫的,一直沒詳細搞,今天整理了一下,感覺挺實用的.
IoC定義接口:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace System { /// <summary> /// 一個接口,支持IoC定義 /// </summary> public interface IIoCDefine { /// <summary> /// 定義類型 /// </summary> /// <param name="type"></param> /// <param name="implType"></param> void Define(Type type, Type implType); /// <summary> /// 定義類型 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="Impl"></typeparam> void Define<T, Impl>() where Impl : T; } }
IoC解析接口:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace System { /// <summary> /// 一個接口,支持IoC解析 /// </summary> public interface IIoCResolve { /// <summary> /// 解析類型 /// </summary> /// <param name="type"></param> object Resolve(Type type); /// <summary> /// 解析類型 /// </summary> /// <typeparam name="T"></typeparam> T Resolve<T>(); } }
具體實現:

using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; namespace System { /// <summary> /// 支持定義解析 /// </summary> internal class ResolveBase : IIoCResolve, IIoCDefine { ICache<Type, Type> _typeMaps = CacheFactory.CreateCache<Type, Type>(); ICache<string, Type> _genericTypeMaps = CacheFactory.CreateCache<string, Type>(); /// <summary> /// 定義類型 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="Impl"></typeparam> public void Define<T, Impl>() where Impl : T { Define(typeof(T), typeof(Impl)); } /// <summary> /// 定義類型 /// </summary> /// <param name="type"></param> /// <param name="implType"></param> public void Define(Type type, Type implType) { if (type == null) { throw Error.ArgumentNullException("type"); } if (implType == null) { throw Error.ArgumentNullException("implType"); } if (implType.IsInterface || implType.IsAbstract) { throw Error.ArgumentException("不能是抽象類型或接口", "implType"); } if (!type.IsGenericTypeDefinition == implType.IsGenericTypeDefinition) { throw Error.ArgumentException("泛型不能與非泛型互轉", "implType"); } if (!implType.IsGenericTypeDefinition && !type.IsAssignableFrom(implType) && !type.GetTypeInfo().IsAssignableFrom(implType)) { throw Error.ArgumentException("不是子類", "implType"); } _typeMaps[type] = implType; if (type.IsGenericType) { _genericTypeMaps[GetGenericTypeDefinitionKey(type)] = implType; } } string GetGenericTypeDefinitionKey(Type type) { // var temp = _typeMaps.Keys.FirstOrDefault(o => o.IsGenericType && o.Name == type.Name && o.Namespace == o.Namespace && o.Module.Equals(type.Module)); //return type.Name + "_" + type.Namespace + "_" + type.Module.Name; return type.FullName + "_" + type.Module.Name; } /// <summary> /// 得到類型實例 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public T Resolve<T>() { Type type = typeof(T); return (T)Resolve(type); } /// <summary> /// 得到類型實例 /// </summary> /// <returns></returns> public object Resolve(Type type) { var instanceType = GetInstanceType(type); //if (instanceType.IsAbstract || instanceType.IsInterface) //{ // throw Error.ArgumentException("解析失敗 : 不能是接口或抽象類"); //} return ActivatorCache.CreateInstance(instanceType); // return Activator.CreateInstance(instanceType); } /// <summary> /// 得到解析類型 /// </summary> /// <param name="type"></param> /// <returns></returns> Type GetInstanceType(Type type) { if (type == null) { throw Error.ArgumentNullException("type"); } Type instanceType; if (!type.IsGenericType) { //如果非泛型,直接拿緩存 instanceType = _typeMaps[type]; if (instanceType == null) { throw Error.ArgumentException("解析失敗 : 未定義解析類型"); } return instanceType; } //是泛型 instanceType = _genericTypeMaps[GetGenericTypeDefinitionKey(type)]; if (instanceType == null) { if (type.IsGenericTypeDefinition) { throw Error.ArgumentException("解析失敗 : 未定義解析類型"); } //找不到具體泛型類型 //從泛型定義中找 var genericType = type.GetGenericTypeDefinition(); instanceType = _genericTypeMaps[GetGenericTypeDefinitionKey(genericType)]; if (instanceType == null) { throw Error.ArgumentException("解析失敗 : 未定義解析類型"); } instanceType = instanceType.MakeGenericType(type.GenericTypeArguments); } if (type.IsGenericTypeDefinition) { //指定泛型參數類型 var gType = instanceType.MakeGenericType(type.GenericTypeArguments); instanceType = gType; } return instanceType; } //bool Equals(Type[] types1, Type[] types2) //{ // if (types1 == null || types2 == null) // { // return false; // } // if (types1.Length != types2.Length) // { // return false; // } // int length = types1.Length; // for (int i = 0; i < length; i++) // { // var type1 = types1[i]; // var type2 = types2[i]; // if (!types1.Equals(type2) && !(type1.IsAssignableFrom(type2) || type2.IsAssignableFrom(type1))) // { // return false; // } // } // return true; //} public object Resolve(Type type, params object[] values) { var instanceType = GetInstanceType(type); if (instanceType.IsAbstract || instanceType.IsInterface) { throw Error.ArgumentException("解析失敗 : 不能是接口或抽象類"); } var types = values.Select(o => o.GetType()).ToArray(); return ActivatorCache.CreateInstance(instanceType, values); // return Activator.CreateInstance(instanceType, values); } public T Resolve<T>(params object[] values) { return (T)Resolve(typeof(T), values); } } }
給個入口:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace System { /// <summary> /// IoC入口對象 /// </summary> public sealed class IoCManager : IIoCResolve, IIoCDefine { IoCManager() { var resolve = new ResolveBase(); _resolve = resolve; _define = resolve; } public static readonly IoCManager Instance = new IoCManager(); IIoCResolve _resolve; IIoCDefine _define; /// <summary> /// 定義類型 /// </summary> /// <param name="type"></param> /// <param name="implType"></param> public void Define(Type type, Type implType) { _define.Define(type, implType); } /// <summary> /// 定義類型 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="Impl"></typeparam> public void Define<T, Impl>() where Impl : T { _define.Define<T, Impl>(); } /// <summary> /// 解析類型 /// </summary> /// <param name="type"></param> /// <param name="implType"></param> public object Resolve(Type type) { return _resolve.Resolve(type); } /// <summary> /// 解析類型 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="Impl"></typeparam> public T Resolve<T>() { return _resolve.Resolve<T>(); } } }
到這里就大功告成了!!!
測試:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Dai.CommonLib.Tests.Models { public interface TestInterface { } public interface TestInterface<T>:TestInterface { } class TestClass : TestInterface { } class TestClass<T> : TestInterface<T> { } class TestClass1<T> : TestClass<T> { } }
[TestMethod] public void TestMethod2() { IoCManager.Instance.Define(typeof(TestInterface), typeof(TestClass<decimal>)); IoCManager.Instance.Define(typeof(TestInterface<>), typeof(TestClass<>)); IoCManager.Instance.Define(typeof(TestInterface<string>), typeof(TestClass1<string>)); var model = IoCManager.Instance.Resolve<TestInterface>(); var model1 = IoCManager.Instance.Resolve<TestInterface<int>>(); var model2 = IoCManager.Instance.Resolve<TestInterface<string>>(); Assert.IsTrue(model is TestClass<decimal>); Assert.IsTrue(model1 is TestClass<int>); Assert.IsTrue(model2 is TestClass1<string>); IoCManager.Instance.Define(typeof(TestInterface), typeof(TestClass)); var model3 = IoCManager.Instance.Resolve<TestInterface>(); Assert.IsTrue(model3 is TestClass); }
優點: 支持泛型,如果指定了具體的泛型類型,那優先解析具體類型,否則從泛型類型定義中替換具體泛型類型參數,如上面的代碼的 TestClass和TestClass1類型
下次寫個Aop Inject 靜態編織注入的文章