日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

框架前期准备篇之AutoFac常见用法总结 转载

發布時間:2024/8/26 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 框架前期准备篇之AutoFac常见用法总结 转载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

框架前期準備篇之AutoFac常見用法總結

?

一. 說在前面的話

  凡是大約工作在兩年以上的朋友們,或多或少都會接觸到一些框架搭建方面的知識,只要一談到框架搭建這個問題或者最佳用法這個問題,勢必會引起一點點小小的風波,我說我的好,他說他的好,非常容易罵架,所以在本節乃至該系列我僅僅是總結了一下自己日常中的一些用法,談一下自己淺陋的見解,談不上最佳,只要不誤導新手 能有點幫助作用就可以了,如您不喜歡,請“右上角? 謝謝”。

  在框架搭建過程中,在層與層的解耦方面,勢必會涉及到IOC框架,.Net 平臺下我用過的IOC框架主要是: Spring.Net 、Unity、AutoFac,當然還有Castle(我沒用過,就不發表任何評論了), 在用過的IOC框架中,Spring.Net 相對很老了,貌似在2015年就不在更新了,但基本的功能也夠用了。 現階段用的最多的就是Unity和AutoFac了,版本更新也比較快,Unity大約一年前寫過兩篇文章了,本次在該框架系列也會考慮更新一下Unity,本節主要介紹一下AutoFac的幾個基本用法。

  先說一下兩個概念IOC和DI,我的理解:

  ① IOC:調用者不再創建(不自己new)被調用者的實例,而是交給容器去創建(AutoFac就充當這里的容器),這就是控制反轉。

  ② DI:容器創建好的實例再注入調用者的過程,就是依賴注入(比如:屬性注入、構造函數注入等)。

AutoFac的信息:

  ①?官網地址:https://autofac.org/

  ② 官方文檔:http://autofac.readthedocs.io/en/latest/index.html

  ③ 最新版本:4.8.1 (截止2018-08-21)

  本節的內容主要包括:

    1. 在使用IOC框架之前的幾種創建對象的方式。

    2. AutoFac的基本用法和幾種生命周期。

    3. AutoFac和Asp.Net MVC5進行整合,利用屬性的方式進行注入。

事先說明一下本節要用到的實現類和接口類:

(1). Ypf.BLL層中包括:CatBLL、DogBLL、RoleBLL、UserBLL。

?

1?? public class CatBLL : IAnimalBLL

2???? {

3???????? public string Introduce()

4???????? {

5???????????? return "我是貓";

6???????? }

7???? }

CatBLL

?

1?? public class DogBLL : IAnimalBLL

2???? {

3???????? public string Introduce()

4???????? {

5???????????? return "我是狗";

6???????? }

7???? }

DogBLL

?

?1?? public class RoleBLL : IRoleBLL

?2???? {

?3

?4???????? public IUserBLL userBLL { get; set; }

?5

?6???????? /// <summary>

?7???????? /// 展示角色信息

?8???????? /// </summary>

?9???????? /// <returns></returns>

10???????? public string ShowRoleInfor()

11???????? {

12???????????? return "我是管理員角色";

13???????? }

14

15

16???????? public string ShowDIDemo()

17???????? {

18???????????? return "哈哈:" + userBLL.GetUserInfor();

19???????? }

20

21???? }

RoleBLL

?

?1? public class UserBLL : IUserBLL,IPeopleBLL

?2???? {

?3???????? /// <summary>

?4???????? /// 獲取用戶信息

?5???????? /// </summary>

?6???????? /// <returns></returns>

?7???????? public string GetUserInfor()

?8???????? {

?9???????????? return "我是獲取用戶信息的方法";

10???????? }

11

12???????? /// <summary>

13???????? /// 自我介紹

14???????? /// </summary>

15???????? /// <returns></returns>

16???????? public string Introduce()

17???????? {

18???????????? return "我是ypf";

19???????? }

20???? }

UserBLL

(2). Ypf.IBLL層包括:IAnimalBLL、IPeopleBLL、IRoleBLL、IUserBLL。

?

1? public interface IAnimalBLL

2???? {

3???????? string Introduce();

4???? }

IAnimalBLL

?

1? public interface IPeopleBLL

2???? {

3???????? //自我介紹

4???????? string Introduce();

5???? }

IPeopleBLL

?

1?? public interface IRoleBLL

2???? {

3???????? string ShowRoleInfor();

4

5???????? string ShowDIDemo();

6

7???? }

IRoleBLL

?

1? public interface IUserBLL

2???? {

3???????? string GetUserInfor();

4???? }

IUserBLL

?

二. 引入IOC框架之前的幾個寫法

1.?最原始的方式直接new(需添加對BLL層的引用)

1 {

2??? UserBLL userBll = new UserBLL();

3??? var result1 = userBll.GetUserInfor();

4??? Console.WriteLine(result1);

5 }

?

2. 面向接口編程(仍需添加對BLL層的引用)

1?? {

2????? IUserBLL userBll = new UserBLL();

3????? var result1 = userBll.GetUserInfor();

4????? Console.WriteLine(result1);

5?? }

?

3.?接口+反射(只需將BLL層的程序集拷貝進來)

?1 {

?2?? Assembly ass = Assembly.Load("Ypf.BLL");

?3?? Type type = ass.GetType("Ypf.BLL.UserBLL");

?4?? //調用默認的無參構造函數進行對象的創建

?5?? object myUserBLL = Activator.CreateInstance(type);

?6?? IUserBLL userBLL = (IUserBLL)myUserBLL;

?7?? var result1 = userBLL.GetUserInfor();

?8?? Console.WriteLine(result1);

?9

10 }

?

4. 手寫IOC(反射+簡單工廠+配置文件)【需將BLL層的程序集拷貝進來】

?配置文件代碼:

? <appSettings>

??? <!--直接修改配置文件,可以切換IUserBLL的實現類,發布后可以直接通過改配置文件,代碼什么也不用改,體會:反射+面向接口編程-->

??? <add key="DllName" value="Ypf.BLL"/>

??? <add key="ClassName" value="Ypf.BLL.UserBLL"/>

? </appSettings>

簡單工廠代碼:

?1???? /// <summary>

?2???? /// 簡單工廠,隔離對象的創建

?3???? /// </summary>

?4??? public class SimpleFactory

?5???? {

?6???????? private static string DllName = ConfigurationManager.AppSettings["DllName"];

?7???????? private static string ClassName = ConfigurationManager.AppSettings["ClassName"];

?8???????? public static IUserBLL CreateInstance()

?9???????? {

10???????????? Assembly ass = Assembly.Load(DllName);

11???????????? Type type = ass.GetType(ClassName);

12???????????? object obj = Activator.CreateInstance(type);

13???????????? return (IUserBLL)obj;

14???????? }

15???? }

調用代碼:

1 {

2?????? IUserBLL userBLL = SimpleFactory.CreateInstance();

3?????? var result = userBLL.GetUserInfor();

4?????? Console.WriteLine(result);

5 }

?

三. AutoFac常見用法總結

1. 基本用法

?  同時添加對Ypf.BLL層和Ypf.IBLL層的引用,然后 聲明容器→注冊實例→解析對象→調用方法、進行測試,代碼如下:

1? {

2????? ContainerBuilder builder = new ContainerBuilder();

3????? //把UserBLL注冊為IUserBLL實現類,當請求IUserBLL接口的時候,返回UserBLL對象

4????? builder.RegisterType<UserBLL>().As<IUserBLL>();

5????? IContainer resolver = builder.Build();

6????? IUserBLL userBLL = resolver.Resolve<IUserBLL>();

7????? var result1 = userBLL.GetUserInfor();

8????? Console.WriteLine(result1);

9 }

  評價:這種用法單純的是為了介紹AutoFac中的幾個方法,僅此而已,在實際開發沒有這么用的,坑比用法,起不到任何解耦的作用。

?

2.?AsImplementedInterfaces的用法

?  在很多情況下,一個類可能實現了多個接口, 如果我們通過??builder.RegisterType<xxxBLL>().As<IxxxBLL>(); 這種方式按部就班排著把這個類注冊給每個接口,實現幾個接口,就要寫幾行注冊代碼,很繁瑣,我們可以通過?AsImplementedInterfaces()?方法,可以把一個類注冊給它實現的全部接口。

?  這樣的話,想用哪個接口,通過Resolve解析即可,代碼如下:

?1 {

?2????? ContainerBuilder builder = new ContainerBuilder();

?3????? //這樣請求UserBLL實現的任何接口的時候都會返回 UserBLL 對象。

?4????? builder.RegisterType<UserBLL>().AsImplementedInterfaces();

?5????? IContainer resolver = builder.Build();

?6????? IUserBLL iUserBLL = resolver.Resolve<IUserBLL>();

?7????? IPeopleBLL iPeopleBLL = resolver.Resolve<IPeopleBLL>();

?8

?9????? var r1 = iUserBLL.GetUserInfor();

10????? var r2 = iPeopleBLL.Introduce();

11

12????? Console.WriteLine(r1);

13????? Console.WriteLine(r2);

14 }

  評價:同時添加對Ypf.BLL層和Ypf.IBLL層的引用,這里也是單純的為了介紹AsImplementedInterfaces()的用法,還是存在實現類的身影,在實際開發中沒有這么用的,起不到任何解耦的作用,坑比用法。

?

3.?AutoFac+反射(徹底消滅實現類)

  引入反射的背景:前面兩種方式都需要添加對Ypf.BLL層的引用,麻煩的要死,根本沒有什么改觀,還是緊耦合在一起。并且如果有很多接口和實現類的話,用RegisterType一行一行的去寫,累個半死,在這種情況下引入反射的概念,簡化代碼量,代碼如下:

?1? {

?2?????? ContainerBuilder builder = new ContainerBuilder();

?3?????? //加載實現類的程序集

?4?????? Assembly asm = Assembly.Load("Ypf.BLL");

?5?????? builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces();

?6?????? IContainer resolver = builder.Build();

?7

?8?????? IUserBLL userBLL = resolver.Resolve<IUserBLL>();

?9?????? IPeopleBLL peopleBLL = resolver.Resolve<IPeopleBLL>();

10?????? var r1 = userBLL.GetUserInfor();

11?????? var r2 = peopleBLL.Introduce();

12

13?????? Console.WriteLine(r1);

14?????? Console.WriteLine(r2);

15 }

  評價:徹底擺脫了實現類的身影,與Ypf.BLL層進行了解耦,只需要添加對Ypf.IBLL層的引用,但需要把Ypf.BLL的程序集拷貝到AutoFacTest項目下。

小小的升級一下:

?  把反射那個程序集類寫到配置文件中,然后在代碼中通過讀取配置文件進行進一步的反射,代碼如下:

1? <appSettings>

2???? <add key="DllName" value="Ypf.BLL"/>

3?? </appSettings>

?1? {

?2????? ContainerBuilder builder = new ContainerBuilder();

?3????? //加載實現類的程序集

?4???? string DllName = ConfigurationManager.AppSettings["DllName"];

?5???? Assembly asm = Assembly.Load(DllName);

?6???? builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces();

?7???? IContainer resolver = builder.Build();

?8

?9???? IUserBLL userBLL = resolver.Resolve<IUserBLL>();

10???? IPeopleBLL peopleBLL = resolver.Resolve<IPeopleBLL>();

11???? var r1 = userBLL.GetUserInfor();

12???? var r2 = peopleBLL.Introduce();

13

14???? Console.WriteLine(r1);

15???? Console.WriteLine(r2);

16 }

?

4.?PropertiesAutowired(屬性的自動注入)

  背景:一個實現類中定義了其他類型的接口屬性,比如RoleBLL中定義IUserBLL的接口屬性,而且要對其進行調用,?這個時候就需要通過PropertiesAutowired實現屬性的自動注入了。

  注:只有通過AutoFac創建的對象才能實現屬性的自動注入!!?相關的類、接口要是public類型。

?

?1? public class RoleBLL : IRoleBLL

?2???? {

?3

?4???????? public IUserBLL userBLL { get; set; }

?5

?6???????? /// <summary>

?7???????? /// 展示角色信息

?8???????? /// </summary>

?9???????? /// <returns></returns>

10???????? public string ShowRoleInfor()

11???????? {

12???????????? return "我是管理員角色";

13???????? }

14

15

16???????? public string ShowDIDemo()

17???????? {

18???????????? return "哈哈:" + userBLL.GetUserInfor();

19???????? }

20

21

22

23???? }

RoleBLL

?1 {

?2????? ContainerBuilder builder = new ContainerBuilder();

?3????? //加載實現類的程序集

?4????? Assembly asm = Assembly.Load("Ypf.BLL");

?5????? builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired();

?6????? IContainer resolver = builder.Build();

?7

?8????? IRoleBLL iRoleBLL = resolver.Resolve<IRoleBLL>();

?9????? var r1 = iRoleBLL.ShowDIDemo();

10????? Console.WriteLine(r1);

}

?

  下面測試一下不是AutoFac創建的對象能否實現屬性的自動注入,新建TempTest類,在里面聲明IUserBLL屬性,并且在方法中進行調用,然后new一個TempTest對象,對該showMsg方法進行調用,發現報空指針錯誤,說明userBLL屬性為空,沒能自動注入。

1? public class TempTest

2???? {

3???????? public IUserBLL userBLL { get; set; }

4

5???????? public void showMsg()

6???????? {

7???????????? Console.WriteLine(userBLL.GetUserInfor());

8???????? }

9???? }

1 //測試自己new的對象不能實現屬性的自動注入

2 //下面代碼報空指針錯誤

3 {

4????? TempTest t = new TempTest();

5????? t.showMsg();

6 }

?

5.?1個接口多個實現類的情況

  背景:1個接口有多個實現類的情況(DogBLL 和 CatBLL 都實現了 IAnimalBLL接口)

  分析:resolver.Resolve<IAnimalBLL>();只會返回其中一個類的對象

  解決方案:如果想返回多個實現類的對象,改成 resolver.Resolve<IEnumerable<IAnimalBLL>>()即可。

?1???????????? {

?2???????????????? ContainerBuilder builder = new ContainerBuilder();

?3???????????????? //加載實現類的程序集

?4???????????????? Assembly asm = Assembly.Load("Ypf.BLL");

?5???????????????? builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired();

?6???????????????? IContainer resolver = builder.Build();

?7

?8???????????????? //返回 CalBLL 和 DogBLL 中的一個

?9???????????????? //{

10???????????????? //??? IAnimalBLL iAnimalBLL = resolver.Resolve<IAnimalBLL>();

11???????????????? // ???var r1 = iAnimalBLL.Introduce();

12???????????????? //??? Console.WriteLine(r1);

13???????????????? //}

14

15???????????????? //如何獲取多個呢?

16???????????????? {

17???????????????????? IEnumerable<IAnimalBLL> blls = resolver.Resolve<IEnumerable<IAnimalBLL>>();

18???????????????????? foreach (IAnimalBLL animalBLL in blls)

19???????????????????? {

20???????????????????????? Console.WriteLine(animalBLL.GetType());

21???????????????????????? Console.WriteLine(animalBLL.Introduce());

22???????????????????? }

23???????????????? }

24???????????? }

?

6.?AutoFac的幾種常見生命周期

1. InstancePerDependency:每次請求 Resovle都返回一個新對象。InstancePerDependency()【這也是默認的創建實例的方式。】

2. SingleInstance: 單例,只有在第一次請求的時候創建 。SingleInstance()

3. InstancePerRequest:ASP.Net MVC 專用,每次http請求內一個對象(也可以理解為一個方法內)。InstancePerRequest() 和 CallContext神似

4. InstancePerLifetimeScope:在一個生命周期域中,每一個依賴或調用創建一個單一的共享的實例,且每一個不同的生命周期域,實例是唯一的,不共享的。

?下面測試一下前兩種生命周期

?情況1

?1?? {

?2???? ContainerBuilder builder = new ContainerBuilder();

?3???? //加載實現類的程序集

?4???? Assembly asm = Assembly.Load("Ypf.BLL");

?5???? builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired().InstancePerDependency();

?6???? IContainer resolver = builder.Build();

?7

?8???? IUserBLL u1 = resolver.Resolve<IUserBLL>();

?9???? IUserBLL u2 = resolver.Resolve<IUserBLL>();

10

11???? Console.WriteLine(object.ReferenceEquals(u1, u2));

12

13? }

結果:False,證明InstancePerDependency 每次都創建一個新對象

情況2

?1?? {

?2????? ContainerBuilder builder = new ContainerBuilder();

?3????? //加載實現類的程序集

?4????? Assembly asm = Assembly.Load("Ypf.BLL");

?5????? builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().PropertiesAutowired().SingleInstance();

?6????? IContainer resolver = builder.Build();

?7

?8????? IUserBLL u1 = resolver.Resolve<IUserBLL>();

?9????? IUserBLL u2 = resolver.Resolve<IUserBLL>();

10

11????? Console.WriteLine(object.ReferenceEquals(u1, u2));

12

13 }

結果:true,證明SingleInstance 每次都返回同一個對象。

?

四. AutoFac與MVC整合

1. Controller中通過屬性注入對象

?步驟1:在Ypf.MVC層中添加對Ypf.IBLL層的引用,并將Ypf.BLL的程序集拷貝到 Ypf.MVC中,或者直接改一下Ypf.BLL輸出路徑。

?步驟2:通過Nuget安裝程序集 Autofac.Mvc5。

?步驟3:在Gloabl 注冊 AutoFac代碼。

?1? public class MvcApplication : System.Web.HttpApplication

?2???? {

?3???????? protected void Application_Start()

?4???????? {

?5???????????? AreaRegistration.RegisterAllAreas();

?6???????????? FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

?7???????????? RouteConfig.RegisterRoutes(RouteTable.Routes);

?8???????????? BundleConfig.RegisterBundles(BundleTable.Bundles);

?9

10???????????? /***********下面是AutoFac的注冊*************/

11???????????? //1. 創建容器

12???????????? var builder = new ContainerBuilder();

13???????????? //2. 把當前程序集中的所有Controller都注冊進來

14???????????? builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();

15???????????? //3. 把Ypf.BLL中的所有類注冊給它的全部實現接口,并且把實現類中的屬性也進行注冊

16???????????? //{ Assembly asmService = Assembly.Load("Ypf.BLL"); }

17???????????? //PS:這里可以配合配置文件的,將Ypf.BLL寫到配置文件中

18???????????? string DllName = ConfigurationManager.AppSettings["DllName"];

19???????????? Assembly asmService = Assembly.Load(DllName);

20???????????? builder.RegisterAssemblyTypes(asmService).Where(t => !t.IsAbstract).AsImplementedInterfaces().PropertiesAutowired();

21???????????? var container = builder.Build();

22???????????? //4. 下面這句話表示當mvc創建controller對象的時候,都是由AutoFac為我們創建Controller對象

23???????????? DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

24

25

26???????? }

27???? }

?

步驟4:在Controller中進行調用。

?

2. 普通類中通過代碼獲取對象

  在一個沒有通過AutoFac注冊的普通類中如何獲取接口對象呢,通過DependencyResolver.Current.GetService<IUserBLL>();來獲取。

  代碼如下:

1?? public class Utils

2???? {

3???????? public static string Test()

4???????? {??????

5???????????? IUserBLL userBLL = DependencyResolver.Current.GetService<IUserBLL>();

6???????????? return userBLL.GetUserInfor();

7???????? }

8???? }

?

3. 如何在普通類中通過屬性的方式注入對象

需要有兩個條件:

  ①: 這個普通類的創建必須在Global中通過AutoFac來進行注冊。

  ②: 獲取這個類的時候必須通過 DependencyResolver.Current.GetService<IUserBLL>(); 這種方式來獲取。

?在Global文件中注冊該普通類

?

該普通類CommonHelp的獲取必須通過DependencyResolver.Current.GetService<CommonHelp>();方式來獲取。

?

4. 在單獨線程中獲取對象

  比如在Quartz.Net 中,需要通過下面代碼來獲取。

?

詳細代碼如下:

?{

??????????????? //1.創建作業調度池(Scheduler)

??????????????? IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();

?

??????????????? //2.創建一個具體的作業即job (具體的job需要單獨在一個文件中執行)

??????????????? var job = JobBuilder.Create<HelloJob>().Build();

?

??????????????? //3.創建并配置一個觸發器即trigger?? 1s執行一次

??????????????? var trigger = TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInSeconds(1)

?????????????????????????????????????????????????????????????????????????????? .RepeatForever()).Build();

??????????????? //4.將job和trigger加入到作業調度池中

??????????????? scheduler.ScheduleJob(job, trigger);

?

??????????????? //5.開啟調度

??????????????? scheduler.Start();

}

?1? public class HelloJob:IJob

?2???? {

?3???????? void IJob.Execute(IJobExecutionContext context)

?4???????? {

?5???????????? IUserBLL userBLL;

?6???????????? var container = AutofacDependencyResolver.Current.ApplicationContainer;

?7???????????? using (container.BeginLifetimeScope())

?8???????????? {

?9???????????????? userBLL = container.Resolve<IUserBLL>();

10???????????? }

11???????????? //下面代碼只是測試

12???????????? Console.WriteLine(userBLL.GetUserInfor());

13???????? }

14???? }

?

?

?

?

?

?

?

!

  • 作???????者 :?Yaopengfei(姚鵬飛)
  • 博客地址 :?http://www.cnblogs.com/yaopengfei/
  • 聲?????明1 : 本人才疏學淺,用郭德綱的話說“我是一個小學生”,如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲?????明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。

?

?

轉載于:https://www.cnblogs.com/Jeely/p/11004678.html

總結

以上是生活随笔為你收集整理的框架前期准备篇之AutoFac常见用法总结 转载的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。