[toc] 前言 周末加班,下午犯困,整理下之前鼓搗過的東西,看過我之前的webapi系列的讀者知道,我之前試過Aspect,但是升級到3.0之後沒往下去試了,當時還留了個坑,這不,現在果斷移除了換成這個了。 Autofac 這個第三方類庫呢,是Ioc的容器,可以簡化我們很大的工作量,比如說在之前我 ...
目錄
前言
周末加班,下午犯困,整理下之前鼓搗過的東西,看過我之前的webapi系列的讀者知道,我之前試過Aspect,但是升級到3.0之後沒往下去試了,當時還留了個坑,這不,現在果斷移除了換成這個了。
Autofac
這個第三方類庫呢,是Ioc的容器,可以簡化我們很大的工作量,比如說在之前我們需要寫個類去聲明介面與實現,而用了這個容器呢,就不需要了,當然還是需要些配置的。
首先,引入第三方類庫,不多說。
然後開始配置吧,首先先來看Program,添加AutofacServiceProviderFactory。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
改完之後呢,我們果斷就來到了Startup,只要是配置,當然要看入口文件跟這個配置文件了。
3.x呢有個變化就是Autofac要通過ConfigureContainer這個傳入容器的方法來配置了,不需要自己再創建。
private static readonly List<string> _Assemblies = new List<string>()
{
"April.Service"
};
public void ConfigureContainer(ContainerBuilder container)
{
var assemblys = _Assemblies.Select(x => Assembly.Load(x)).ToList();
List<Type> allTypes = new List<Type>();
assemblys.ForEach(aAssembly =>
{
allTypes.AddRange(aAssembly.GetTypes());
});
// 通過Autofac自動完成依賴註入
container.RegisterTypes(allTypes.ToArray())
.AsImplementedInterfaces()
.PropertiesAutowired()
.InstancePerDependency();
// 註冊Controller
container.RegisterAssemblyTypes(typeof(Startup).GetTypeInfo().Assembly)
.Where(t => typeof(Controller).IsAssignableFrom(t) && t.Name.EndsWith("Controller", StringComparison.Ordinal))
.PropertiesAutowired();
}
通過RegisterTypes的註冊方法將對應工程,也就是April.Service下的類介面與實現自動綁定,當然你也可以通過註冊介面的方法一個個來,但是我懶,比如:
// 一個
builder.RegisterType<StudentService>().As<IStudentService>();
// 一對多
builder.RegisterType<StudentService>().As<IStudentService>().As<ITestService>();
這裡註意,聲明綁定一般是一對一,當然也可以是一對多,如果多次註冊聲明一個類,會取最後一次註冊的聲明作為實際操作的類。
好了,配置完成之後,我們來試下效果吧(當然我是已經註釋掉之前的ServiceInjection這個聲明方法了)。
在我們訪問Values的時候,我們看下IStudentService是否是null。
OK,這已經說明通過Autofac這個容器,已經完成了一個工程裡面的介面與實現的依賴關係了。
添加一個Util來隨時調用
在接觸的朋友中,有人給我反饋個信息,我不想每次寫方法都要構造函數來傳介面方法給我,也就是說我不要你覺得,我要我覺得。
好啊,你覺得方法自己要啥拿啥,可以,來個Util吧。
public class AutofacUtil
{
public static ILifetimeScope Container { get; set; }
/// <summary>
/// 獲取服務(Single)
/// </summary>
/// <typeparam name="T">介面類型</typeparam>
/// <returns></returns>
public static T GetService<T>() where T : class
{
return Container.Resolve<T>();
}
/// <summary>
/// 獲取服務(請求生命周期內)
/// </summary>
/// <typeparam name="T">介面類型</typeparam>
/// <returns></returns>
public static T GetScopeService<T>() where T : class
{
return (T)GetService<IHttpContextAccessor>().HttpContext.RequestServices.GetService(typeof(T));
}
}
在用之前,我們需要針對Container來個聲明實例化,Startup中的Configure添加下麵一句。
AutofacUtil.Container = app.ApplicationServices.GetAutofacRoot();
修改Values中的一部分來通過實例化的方式來調用介面。
IStudentService studentService = AutofacUtil.GetScopeService<IStudentService>();
StudentEntity entity = new StudentEntity
{
//新增
Name = "小明",
Age = 18,
Number = "007",
Sex = 0,
Address = "大洛陽"
};
studentService.Insert(entity);
讓我們來看下效果吧。
兩種方法,看個人習慣吧,我是推薦通過註入的方式,通過構造函數的方式來獲取介面實現。
小結
簡單記錄平時鼓搗的點點滴滴,有時候真是覺得,還是要多看多鼓搗,就像這個容器,在之前我通過一行一行的介面+實現來做綁定聲明,現在呢,只需要改造下,就可以一鍵無腦實例化,第三方庫的使用與否,個人覺得還是能踩著巨人的肩膀哪怕靠著也可以,自己一步步爬固然可嘉,也要學會變通,這樣方能提高效率,路漫漫其修遠兮。
代碼地址
預告
April-Admin,總算是要有個前後端聯動的工程了,一個名副其實的基礎工程。
前端基於Ant Design Pro
後端當然是net core 3.1了