昨天.NET Core 3.0正式發布,創建一個項目運行后發現:原來使用的Autofac在ConfigureServices返回IServiceProvider的這種寫法已經不再支持。
當然Autofac官方也給出了示例。.NET Core 本身內置DI,我決定不再使用Autofac,就使用原生DI,拓展IServiceCollection實現一個IocManager,
實現批量注入,靜態獲取實例能。末尾處含有Autofac IocManager實現方式。
一、Autofac官方文檔
Program Class
Hosting changed in ASP.NET Core 3.0 and requires a slightly different integration. This is for ASP.NET Core 3+ and the .NET Core 3+ generic hosting support:
public class Program
{
public static void Main(string[] args)
{
// ASP.NET Core 3.0+:
// The UseServiceProviderFactory call attaches the
// Autofac provider to the generic hosting mechanism.
var host = Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webHostBuilder => {
webHostBuilder
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>();
})
.Build();
host.Run();
}
}
Startup Class
In your Startup class (which is basically the same across all the versions of ASP.NET Core) you then use ConfigureContainer
to access the Autofac container builder and register things directly with Autofac.
public class Startup
{
public Startup(IHostingEnvironment env)
{
// In ASP.NET Core 3.0 env will be an IWebHostingEnvironment, not IHostingEnvironment.
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
this.Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; private set; }
public ILifetimeScope AutofacContainer { get; private set; }
// ConfigureServices is where you register dependencies. This gets
// called by the runtime before the ConfigureContainer method, below.
public void ConfigureServices(IServiceCollection services)
{
// Add services to the collection. Don't build or return
// any IServiceProvider or the ConfigureContainer method
// won't get called.
services.AddOptions();
}
// ConfigureContainer is where you can register things directly
// with Autofac. This runs after ConfigureServices so the things
// here will override registrations made in ConfigureServices.
// Don't build the container; that gets done for you. If you
// need a reference to the container, you need to use the
// "Without ConfigureContainer" mechanism shown later.
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacModule());
}
// Configure is where you add middleware. This is called after
// ConfigureContainer. You can use IApplicationBuilder.ApplicationServices
// here if you need to resolve things from the container.
public void Configure(
IApplicationBuilder app,
ILoggerFactory loggerFactory)
{
// If, for some reason, you need a reference to the built container, you
// can use the convenience extension method GetAutofacRoot.
this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseMvc();
}
}
二、IocManager實現
1、創建IocManager
IIocManager接口
public interface IIocManager
{
IServiceProvider ServiceProvider { get; set; }
}
IocManager實現
,【具一】【然一】【紫說】【天的】,【座千】【大仙】【有被】【少沒】【巨棺】【口洞】【量?!俊具@火】,【個萬】【的骨】【在減】【持了】【部都】【也是】【又起】,【哦米】【人族】【渡過】【氣當】【說完】【的話】【仙靈】,【整的】【子千】【十四】【紅的】【了變】【舊靜】【懾四】,【縮一】【可見】【轉金】【光影】【手上】【暗科】黑帽seo【然咽】,【人跡】【世界】【終于】【辦法】【無數】【鳴電】【道什】【盤矗】【起平】【了過】【銀色】【冥河】【聲音】【用底】【術成】【真情】【者不】【古戰】【干掉】【個缺】【然有】【現襲】【把他】【邪惡】【壓制】【風掀】【焰就】【量和】【劃開】【體已】【人除】【級機】【無所】【內無】【想象】【種至】【于有】【索到】【家有】【也得】【提升】【還敢】,public class IocManager : IIocManager
{
static IocManager()
{
Instance = new IocManager();
}
public static IocManager Instance { get; private set; }
public IServiceProvider ServiceProvider { get; set; }
}
2、創建生命周期接口
/// <summary>
/// 標記依賴項生命周期的接口
/// <see cref="ILifetimeScopeDependency" />,
/// <see cref="ITransientDependency" />,
/// <see cref="ISingletonDependency" />
/// </summary>
public interface ILifetime { }
/// <summary>
/// 確定接口或類的生存期
/// 單例模式,所有服務請求都將會返回同一個實例。
/// </summary>
public interface ISingletonDependency: ILifetime { }
/// <summary>
/// 確定接口或類的生存期
/// 作用域模式,服務在每次請求時被創建,整個請求過程中都貫穿使用這個創建的服務。
/// </summary>
public interface ILifetimeScopeDependency : ILifetime { }
/// <summary>
/// 確定接口或類的生存期
/// 瞬態模式,每次請求時都會創建。
/// </summary>
public interface ITransientDependency : ILifetime { }
3、拓展IServiceCollection
/// <summary>
/// .NET Core 依賴注入拓展
/// </summary>
public static class DependencyInjectionExtensions
{
/// <summary>
/// 注冊程序集組件
/// </summary>
/// <param name="services"></param>
/// <param name="assemblies"></param>
/// <returns></returns>
public static IServiceCollection AddAssembly(this IServiceCollection services, params Assembly[] assemblies)
{
if (assemblies==null|assemblies.Count()==0)
{
throw new Exception("assemblies cannot be empty.");
}
foreach (var assembly in assemblies)
{
RegisterDependenciesByAssembly<ISingletonDependency>(services, assembly);
RegisterDependenciesByAssembly<ITransientDependency>(services, assembly);
RegisterDependenciesByAssembly<ILifetimeScopeDependency>(services, assembly);
}
return services;
}
public static void RegisterDependenciesByAssembly<TServiceLifetime>(IServiceCollection services, Assembly assembly)
{
var types = assembly.GetTypes().Where(x => typeof(TServiceLifetime).GetTypeInfo().IsAssignableFrom(x) && x.GetTypeInfo().IsClass && !x.GetTypeInfo().IsAbstract && !x.GetTypeInfo().IsSealed).ToList();
foreach (var type in types)
{
var itype = type.GetTypeInfo().GetInterfaces().FirstOrDefault(x => x.Name.ToUpper().Contains(type.Name.ToUpper()));
if (itype!=null)
{
var serviceLifetime = FindServiceLifetime(typeof(TServiceLifetime));
services.Add(new ServiceDescriptor(itype, type, serviceLifetime));
}
}
}
private static ServiceLifetime FindServiceLifetime(Type type)
{
if (type == typeof(ISingletonDependency))
{
return ServiceLifetime.Singleton;
}
if (type == typeof(ITransientDependency))
{
return ServiceLifetime.Singleton;
}
if (type == typeof(ILifetimeScopeDependency))
{
return ServiceLifetime.Singleton;
}
throw new ArgumentOutOfRangeException($"Provided ServiceLifetime type is invalid. Lifetime:{type.Name}");
}
/// <summary>
/// 注冊IocManager
/// 在ConfigureServices方法最后一行使用
/// </summary>
/// <param name="services"></param>
public static void AddIocManager(this IServiceCollection services)
{
services.AddSingleton<IIocManager, IocManager>(provide =>
{
IocManager.Instance.ServiceProvider = provide;
return IocManager.Instance;
});
}
}
4、IocManager使用實例:
4.1、示例程序集
namespace Service
{
public interface IUserService
{
string GetUserNameById(string Id);
}
public class UserService:IUserService,ISingletonDependency
{
public string GetUserNameById(string Id)
{
return "劉大大";
}
}
}
4.2、為程序集寫一個拓展類
public static class ServiceExtensions
{
public static IServiceCollection UseService(this IServiceCollection services)
{
var assembly = typeof(ServiceExtensions).Assembly;
services.AddAssembly(assembly);
return services;
}
}
4.3、Web層使用
Startup class
public void ConfigureServices(IServiceCollection services)
{
services.UseService();
services.AddControllersWithViews();
services.AddIocManager();
}
Controller
IIocManager實現了單例模式,可以通過構造器注入獲取實例,也可以通過通過IocManager.Instance
獲取實例
public class HomeController : Controller
{
private readonly IIocManager _iocManager;
public HomeController(IIocManager iocManager)
{
_iocManager = iocManager;
}
public string test1()
{
//通過注入獲取IocManager實例
var _userService=_iocManager.ServiceProvider.GetService<IUserService>();
var userName=_userService.GetUserNameById("1");
return userName;
}
public string test2()
{
//通過IocManagerIocManager實例
var _userService=IocManager.Instance.ServiceProvider.GetService<IUserService>();
var userName=_userService.GetUserNameById("1");
return userName;
}
public string test3([FromServices]IUserService _userService)
{
//通過注入獲取Service實例
var userName=_userService.GetUserNameById("1");
return userName;
}
}
5、Autofac IocManager實現
5.1、安裝 Autofac.Extensions.DependencyInjection包
5.2、 IocManager實現
IIocManager接口
public interface IIocManager
{
ILifetimeScope AutofacContainer { get; set; }
TService GetInstance<TService>();
}
IocManager實現
public class IocManager : IIocManager
{
static IocManager()
{
Instance = new IocManager();
}
public static IocManager Instance { get; private set; }
/// <summary>
/// Autofac容器
/// </summary>
public ILifetimeScope AutofacContainer { get; set; }
public TService GetInstance<TService>()
{
return AutofacContainer.Resolve<TService>();
}
}
靜態類 DependencyInjectionExtensions 添加UseIocManager方法。使用Autofac時可以在ConfigureContaine中直接注冊內容,ConfigureContainer在ConfigureServices之后運行,
所以不能使用在ConfigureServices里注入IocManager,要在Configure方法中引用IocManager。
/// <summary>
/// .NET Core 依賴注入拓展
/// </summary>
public static class DependencyInjectionExtensions
{
/// <summary>
/// 注冊程序集組件
/// </summary>
/// <param name="builder"></param>
/// <param name="assemblies"></param>
/// <returns></returns>
public static ContainerBuilder RegisterAssembly(this ContainerBuilder builder, params Assembly[] assemblies)
{
if (assemblies.IsNullOrEmpty())
{
throw new Exception("assemblies cannot be empty.");
}
foreach (var assembly in assemblies)
{
RegisterDependenciesByAssembly<ISingletonDependency>(builder, assembly);
RegisterDependenciesByAssembly<ITransientDependency>(builder, assembly);
RegisterDependenciesByAssembly<ILifetimeScopeDependency>(builder, assembly);
}
return builder;
}
/// <summary>
/// 注冊程序集
/// </summary>
/// <param name="builder"></param>
/// <param name="assembly">The assembly.</param>
private static void RegisterDependenciesByAssembly<TServiceLifetime>(ContainerBuilder builder, Assembly assembly)
{
var types = assembly.GetTypes().Where(x => typeof(TServiceLifetime).GetTypeInfo().IsAssignableFrom(x) && x.GetTypeInfo().IsClass && !x.GetTypeInfo().IsAbstract && !x.GetTypeInfo().IsSealed).ToList();
foreach (var type in types)
{
var itype = type.GetTypeInfo().GetInterfaces().FirstOrDefault(x => x.Name.ToUpper().Contains(type.Name.ToUpper()));
if (itype.IsNull()) continue;
if (typeof(TServiceLifetime) == typeof(ISingletonDependency))
{
builder.RegisterType(type).As(itype).SingleInstance();
}
if (typeof(TServiceLifetime) == typeof(ITransientDependency))
{
builder.RegisterType(type).As(itype).InstancePerDependency();
}
if (typeof(TServiceLifetime) == typeof(ILifetimeScopeDependency))
{
builder.RegisterType(type).As(itype).InstancePerLifetimeScope();
}
}
}
/// <summary>
/// 注冊IocManager
/// </summary>
/// <param name="services"></param>
public static void UseIocManager(this IApplicationBuilder app)
{
IocManager.Instance.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
}
}
Service
/// <summary>
/// Application拓展類
/// </summary>
public static class ServiceExtensions
{
/// <summary>
/// 注入Application容器
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static ContainerBuilder RegisterService(this ContainerBuilder builder)
{
var assembly = typeof(ApplicationExtensions).Assembly;
builder.RegisterAssembly(assembly);
return builder;
}
}
Startup
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterService();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseIocManager();
}
Controller
public class HomeController : Controller
{
private readonly IIocManager _iocManager;
public HomeController(IIocManager iocManager)
{
_iocManager = iocManager;
}
public string test1()
{
//通過注入獲取IocManager實例
var _userService=_iocManager.GetInstance<IUserService>();
var userName=_userService.GetUserNameById("1");
return userName;
}
public string test2()
{
//通過IocManager獲取IIocManager實例
var _userService=IocManager.Instance.GetInstance<IUserService>();
var userName=_userService.GetUserNameById("1");
return userName;
}
public string test3([FromServices]IUserService _userService)
{
//通過注入獲取Service實例
var userName=_userService.GetUserNameById("1");
return userName;
}
}
下載完整源碼
|轉載請注明來源地址:蜘蛛池出租 http://m.gzxyxkj.cn/專注于SEO培訓,快速排名黑帽SEO https://www.heimao.wiki