IOC+EF+Core项目搭建IOC注入及框架(二)
配置ServiceCollection
/// <summary> /// 表示IServiceCollection的扩展 /// </summary> public static class ServiceCollectionExtensions { /// <summary> /// 向应用程序添加服务并配置服务提供者 /// </summary> /// <param name="services">Collection of service descriptors</param> /// <param name="configuration">Configuration of the application</param> /// <returns>Configured service provider</returns> public static IServiceProvider ConfigureApplicationServices(this IServiceCollection services, IConfiguration configuration) { //添加TestConfig配置参数 services.ConfigureStartupConfig<TestConfig>(configuration.GetSection("Test")); services.AddHttpContextAccessor(); //创建、初始化和配置引擎 var engine = EngineContext.Create(); engine.Initialize(services); IServiceProvider serviceProvider = engine.ConfigureServices(services, configuration); return serviceProvider; } /// <summary> /// 创建、绑定和注册指定的配置参数作为服务 /// </summary> public static TConfig ConfigureStartupConfig<TConfig>(this IServiceCollection services, IConfiguration configuration) where TConfig : class, new() { if (services == null) throw new ArgumentNullException(nameof(services)); if (configuration == null) throw new ArgumentNullException(nameof(configuration)); //create instance of config var config = new TConfig(); //bind it to the appropriate section of configuration configuration.Bind(config); //and register it as a service services.AddSingleton(config); return config; } /// <summary> /// 注册Http上下文存取器 /// </summary> /// <param name="services">Collection of service descriptors</param> /// 服务描述符的集合 public static void AddHttpContextAccessor(this IServiceCollection services) { services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); } }
模型引擎
/// <summary> ///实现这个接口的类可以作为组成Nop引擎的各种服务的门户。 ///Fdit功能、模块和实现通过这个接口访问大多数Nop功能。 /// </summary> public interface IEngine { /// <summary> /// Initialize 引擎 /// </summary> /// <param name="services">Collection of service descriptors</param> void Initialize(IServiceCollection services); /// <summary> /// Add and configure services /// </summary> /// <param name="services">服务描述符的集合</param> /// <param name="configuration">Configuration of the application</param> /// <returns>Service provider</returns> IServiceProvider ConfigureServices(IServiceCollection services, IConfiguration configuration); /// <summary> /// Configure HTTP request 管道 /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> void ConfigureRequestPipeline(IApplicationBuilder application); /// <summary> /// Resolve 集合 /// </summary> /// <typeparam name="T">Type of resolved service</typeparam> /// <returns>Resolved service</returns> T Resolve<T>() where T : class; /// <summary> /// Resolve dependency /// </summary> /// <param name="type">Type of resolved service</param> /// <returns>Resolved service</returns> object Resolve(Type type); /// <summary> /// Resolve dependencies /// </summary> /// <typeparam name="T">Type of resolved services</typeparam> /// <returns>Collection of resolved services</returns> IEnumerable<T> ResolveAll<T>(); /// <summary> /// Resolve unregistered service /// </summary> /// <param name="type">Type of service</param> /// <returns>Resolved service</returns> object ResolveUnregistered(Type type); }
单例模式
/// <summary> /// 单例模式 /// </summary> /// <typeparam name="T"></typeparam> public class Singleton<T> : BaseSingleton { private static T instance; /// <summary> /// The singleton instance for the specified type T. Only one instance (at the time) of this object for each type of T. /// </summary> public static T Instance { get => instance; set { instance = value; AllSingletons[typeof(T)] = value; } } } /// <summary> /// 提供对存储的所有“单例”的访问 <see cref="Singleton{T}"/>. /// </summary> public class BaseSingleton { static BaseSingleton() { AllSingletons = new Dictionary<Type, object>(); } /// <summary> /// 到单例实例的类型字典。 /// </summary> public static IDictionary<Type, object> AllSingletons { get; } }
/// <summary> /// 提供对引擎的单件实例的访问。 /// </summary> public class EngineContext { #region 方法 /// <summary> /// Create a static instance of the Nop engine. /// </summary> [MethodImpl(MethodImplOptions.Synchronized)] public static IEngine Create() { //create NopEngine as engine return Singleton<IEngine>.Instance ?? (Singleton<IEngine>.Instance = new NopEngine()); } /// <summary> /// 将静态引擎实例设置为提供的引擎。使用这个方法来提供您自己的引擎实现。 /// </summary> public static void Replace(IEngine engine) { Singleton<IEngine>.Instance = engine; } #endregion #region 属性 /// <summary> /// 获取单例Nop引擎,用于访问Nop服务。 /// </summary> public static IEngine Current { get { if (Singleton<IEngine>.Instance == null) { Create(); } return Singleton<IEngine>.Instance; } } #endregion }
/// <summary> /// 代表 Nop engine /// </summary> public class NopEngine : IEngine { #region 属性 /// <summary> /// 服务 /// </summary> private IServiceProvider _serviceProvider { get; set; } /// <summary> /// 服务 /// </summary> public virtual IServiceProvider ServiceProvider => _serviceProvider; #endregion #region Utilities /// <summary> /// Get IServiceProvider /// </summary> /// <returns>IServiceProvider</returns> protected IServiceProvider GetServiceProvider() { var accessor = ServiceProvider.GetService<IHttpContextAccessor>(); var context = accessor.HttpContext; //var a=context == null ? null : RequestServices ?? ServiceProvider; context==null?null:SericeProvider return context?.RequestServices ?? ServiceProvider; } /// <summary> /// 创建服务提供者Autofac /// </summary> /// <param name="nopConfig">Startup Nop configuration parameters</param> /// <param name="services">Collection of service descriptors</param> /// <param name="typeFinder">Type finder</param> protected virtual IServiceProvider RegisterDependencies(IServiceCollection services) { var containerBuilder = new ContainerBuilder(); //注册引擎 containerBuilder.RegisterInstance(this).As<IEngine>().SingleInstance(); //数据库 containerBuilder.Register(context => new NopObjectContext(context.Resolve<DbContextOptions<NopObjectContext>>())) .As<IDbContext>().InstancePerLifetimeScope(); //IOC containerBuilder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope(); containerBuilder.RegisterType<Sys_UserService>().As<ISys_UserService>().InstancePerLifetimeScope();//用一组注册的服务描述符填充Autofac容器构建器 containerBuilder.Populate(services); //创建服务提供者 _serviceProvider = new AutofacServiceProvider(containerBuilder.Build()); return _serviceProvider; } #endregion #region 方法 /// <summary> /// Initialize engine /// </summary> /// <param name="services">Collection of service descriptors</param> public void Initialize(IServiceCollection services) { //目前大多数APT供应商都需要TLS 1.2 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; var provider = services.BuildServiceProvider(); var hostingEnvironment = provider.GetRequiredService<IHostingEnvironment>(); var mvcCoreBuilder = services.AddMvcCore(); }
/// <summary> ///添加配置服务 /// </summary> /// <param name="services">Collection of service descriptors</param> /// <param name="configuration">Configuration of the application</param> /// <returns>Service provider</returns> public IServiceProvider ConfigureServices(IServiceCollection services, IConfiguration configuration) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); //数据库连接 var testConfig = services.BuildServiceProvider().GetRequiredService<TestConfig>(); services.AddDbContext<NopObjectContext>(options => options.UseLazyLoadingProxies().UseSqlServer(testConfig.SqlConnection)); services.AddEntityFrameworkSqlServer(); services.AddEntityFrameworkProxies(); //ioc RegisterDependencies(services); services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); return _serviceProvider; } /// <summary> /// Configure HTTP request pipeline /// </summary> /// <param name="application">Builder for configuring an application's request pipeline</param> public void ConfigureRequestPipeline(IApplicationBuilder application) { ////find startup configurations provided by other assemblies //var typeFinder = Resolve<ITypeFinder>(); //var startupConfigurations = typeFinder.FindClassesOfType<INopStartup>(); ////create and sort instances of startup configurations //var instances = startupConfigurations // //.Where(startup => PluginManager.FindPlugin(startup)?.Installed ?? true) //ignore not installed plugins // .Select(startup => (INopStartup)Activator.CreateInstance(startup)) // .OrderBy(startup => startup.Order); ////configure request pipeline //foreach (var instance in instances) // instance.Configure(application); } /// <summary> /// Resolve dependency /// </summary> /// <typeparam name="T">Type of resolved service</typeparam> /// <returns>Resolved service</returns> public T Resolve<T>() where T : class { return (T)GetServiceProvider().GetRequiredService(typeof(T)); } /// <summary> /// Resolve dependency /// </summary> /// <param name="type">Type of resolved service</param> /// <returns>Resolved service</returns> public object Resolve(Type type) { return GetServiceProvider().GetRequiredService(type); } /// <summary> /// Resolve dependencies /// </summary> /// <typeparam name="T">Type of resolved services</typeparam> /// <returns>Collection of resolved services</returns> public IEnumerable<T> ResolveAll<T>() { return (IEnumerable<T>)GetServiceProvider().GetServices(typeof(T)); } /// <summary> /// Resolve unregistered service /// </summary> /// <param name="type">Type of service</param> /// <returns>Resolved service</returns> public virtual object ResolveUnregistered(Type type) { Exception innerException = null; foreach (var constructor in type.GetConstructors()) { try { //try to resolve constructor parameters var parameters = constructor.GetParameters().Select(parameter => { var service = Resolve(parameter.ParameterType); if (service == null) throw new Exception("Unknown dependency"); return service; }); //all is ok, so create instance return Activator.CreateInstance(type, parameters.ToArray()); } catch (Exception ex) { innerException = ex; } } throw new Exception("No constructor was found that had all the dependencies satisfied.", innerException); } #endregion }