Asp.net web form 使用IOC(Unity) 构造函数注入Page,.net Framework 4.7.2
public static class UnityAdapter { private static object _lock = new object(); /// <summary> /// Add a new Unity container in asp.net application. If there is WebObjectActivator already registered, /// it will be chained up. When the new WebObjectActivator can't resolve the type, the previous WebObjectActivator /// will be used. If the previous WebObjectActivator can't resolve it either, DefaultCreateInstance will be used /// which creates instance through none public default constructor based on reflection. /// </summary> /// <returns></returns> public static IUnityContainer AddUnity() { lock (_lock) { HttpRuntime.WebObjectActivator = new ContainerServiceProvider(HttpRuntime.WebObjectActivator); return GetContainer(); } } /// <summary> /// Get most recent added Unity container /// </summary> /// <returns></returns> public static IUnityContainer GetContainer() { return (HttpRuntime.WebObjectActivator as ContainerServiceProvider)?.Container; } }
public static class HttpApplicationExtensions { /// <summary> /// /// </summary> /// <param name="application"></param> /// <returns></returns> public static UnityContainer AddUnity(this HttpApplication application) { if (application == null) { throw new ArgumentNullException(nameof(application)); } return (UnityContainer)UnityAdapter.AddUnity(); } /// <summary> /// /// </summary> /// <returns></returns> public static IUnityContainer GetUnityContainer(this HttpApplication application) { return UnityAdapter.GetContainer();
} }
class ContainerServiceProvider : IServiceProvider, IRegisteredObject { private const int TypesCannontResolveCacheCap = 100000; private readonly IServiceProvider _next; private readonly ConcurrentDictionary<Type, bool> _typesCannotResolve = new ConcurrentDictionary<Type, bool>(); public ContainerServiceProvider(IServiceProvider next) { _next = next; HostingEnvironment.RegisterObject(this); } /// <summary> /// Implementation of IServiceProvider. Asp.net will call this method to /// create the instances of Page/UserControl/HttpModule etc. /// </summary> /// <param name="serviceType"></param> /// <returns></returns> public object GetService(Type serviceType) { // // Try unresolvable types if (_typesCannotResolve.ContainsKey(serviceType)) { return DefaultCreateInstance(serviceType); } // // Try the container object result = null; try { result = Container.Resolve(serviceType); } catch (ResolutionFailedException) { // Ignore and continue } // // Try the next provider if (result == null) { result = _next?.GetService(serviceType); } // // Default activation if (result == null) { if ((result = DefaultCreateInstance(serviceType)) != null) { // Cache it if (_typesCannotResolve.Count < TypesCannontResolveCacheCap) { _typesCannotResolve.TryAdd(serviceType, true); } } } return result; } public IUnityContainer Container { get; internal set; } = new UnityContainer(); public void Stop(bool immediate) { HostingEnvironment.UnregisterObject(this); Container.Dispose(); } internal IServiceProvider NextServiceProvider { get { return _next; } } internal IDictionary<Type, bool> TypeCannotResolveDictionary { get { return _typesCannotResolve; } } protected virtual object DefaultCreateInstance(Type type) { return Activator.CreateInstance( type, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance, null, null, null); } }
引入上面这三个类,然后用nuget 安装UnityIOC,然后在Application_Start中配置
运行效果如下:
Hold on, everything is possible.