ASP.NET Core 3.0 原生DI拓展实现IocManager
<p>昨天<strong>.NET Core 3.0</strong> 正式发布,创建一个项目运行后发现:原来利用的Autofac在ConfigureServices返回IServiceProvider的这种写法已经不再支持。当然Autofac官方也给出了示例。</p><p>.NET Core 自己内置DI,我决定不再利用Autofac,就利用原生DI,拓展IServiceCollection实现一个IocManager,</p>
<p>实现批量注入,静态获取实例功能。</p>
<h2 id="一autofac官方文档">一、Autofac官方文档</h2>
<h3 id="program-class">Program Class</h3>
<p><strong>Hosting changed in ASP.NET Core 3.0</strong> and requires a slightly different integration. This is for ASP.NET Core 3+ and the .NET Core 3+ generic hosting support:</p>
<code>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();
}
}</code>
<h3 id="startup-class">Startup Class</h3>
<p>In your Startup class (which is basically the same across all the versions of ASP.NET Core) you then use <code>ConfigureContainer</code> to access the Autofac container builder and register things directly with Autofac.</p>
<code>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();
}
}</code>
<h2 id="二iocmanager实现">二、IocManager实现</h2>
<h3 id="创建iocmanager">1、创建IocManager</h3>
<code>public interface IIocManager
{
IServiceProvider ServiceProvider { get; set; }
}</code>
<code>public class IocManager : IIocManager
{
static IocManager()
{
Instance = new IocManager();
}
public static IocManager Instance { get; private set; }
public IServiceProvider ServiceProvider { get; set; }
}</code>
<h3 id="创建生命周期接口">2、创建生命周期接口</h3>
<code> /// <summary>
/// 标记依赖项生命周期的接口
/// <see cref="ILifetimeScopeDependency" />,
/// <see cref="ITransientDependency" />,
/// <see cref="ISingletonDependency" />
/// </summary>
public interface ILifetime { }
/// <summary>
/// 确定接口或类的生存期
/// 作用域模式,服务在每次哀求时被创建,整个哀求过程中都贯穿利用这个创建的服务。
/// </summary>
public interface ILifetimeScopeDependency : ILifetime { }
/// <summary>
/// 确定接口或类的生存期
/// 作用域模式,服务在每次哀求时被创建,整个哀求过程中都贯穿利用这个创建的服务。
/// </summary>
public interface ILifetimeScopeDependency : ILifetime { }
/// <summary>
/// 确定接口或类的生存期
/// 瞬态模式,每次哀求时都会创建。
/// </summary>
public interface ITransientDependency : ILifetime { }</code>
<h3 id="拓展iservicecollection">3、拓展IServiceCollection</h3>
<code>/// <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;
});
}
}</code>
<h3 id="iocmanager利用实例">4、IocManager利用实例:</h3>
<h4 id="示例步伐集">4.1、示例步伐集</h4>
<code>namespace Service
{
public interface IUserService
{
string GetUserNameById(string Id);
}
public interface UserService:IUserService,ISingletonDependency
{
public string GetUserNameById(string Id)
{
return "刘大大";
}
}
}</code>
<h4 id="为步伐集写一个拓展类">4.2、为步伐集写一个拓展类</h4>
<code>public static class ServiceExtensions
{
public static IServiceCollection UseService(this IServiceCollection services)
{
var assembly = typeof(ServiceExtensions).Assembly;
services.AddAssembly(assembly);
return services;
}
}</code>
<h4 id="web层利用">4.3、Web层利用</h4>
<h5 id="startup-class-1">Startup class</h5>
<code> public void ConfigureServices(IServiceCollection services)
{
services.UseService();
services.AddControllersWithViews();
services.AddIocManager();
}</code>
<h5 id="controller">Controller</h5>
<p>IIocManager实现了单例模式,可以通过构造器注入获取实例,也可以通过通过<code>IocManager.Instance</code>获取实例</p>
<code> 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()
{
//通过IocManager获取IIocManager实例
var _userService=IocManager.Instance.ServiceProvider.GetService<IUserService>();
var userName=_userService.GetUserNameById("1");
return userName;
}
public string test3(IUserService _userService)
{
//通过注入获取Service实例
var userName=_userService.GetUserNameById("1");
return userName;
}
}</code>
<p><div align="center"></div></p><br><br/><br/><br/><br/><br/>来源:<a href="https://www.cnblogs.com/lwc1st/archive/2019/09/25/11582662.html" target="_blank">https://www.cnblogs.com/lwc1st/archive/2019/09/25/11582662.html</a>
页:
[1]