.Net IOC框架入門之——Autofac


一、簡介

 Autofac是.NET領域最為流行的IOC框架之一,傳說是速度最快的一個

目的

1.依賴注入的目的是為了解耦。
2.不依賴於具體類,而依賴抽象類或者接口,這叫依賴倒置。
3.控制反轉即IoC (Inversion of Control),它把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。所謂的“控制反轉”概念就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器。
4. 微軟的DependencyResolver如何創建controller

 

生命周期

1、InstancePerDependency

對每一個依賴或每一次調用創建一個新的唯一的實例。這也是默認的創建實例的方式。官方文檔解釋:Configure the component so that every dependent component or call to Resolve() gets a new, unique instance (default.) 

2、InstancePerLifetimeScope

在一個生命周期域中,每一個依賴或調用創建一個單一的共享的實例,且每一個不同的生命周期域,實例是唯一的,不共享的。官方文檔解釋:Configure the component so that every dependent component or call to Resolve() within a single ILifetimeScope gets the same, shared instance. Dependent components in different lifetime scopes will get different instances. 

3、InstancePerMatchingLifetimeScope

在一個做標識的生命周期域中,每一個依賴或調用創建一個單一的共享的實例。打了標識了的生命周期域中的子標識域中可以共享父級域中的實例。若在整個繼承層次中沒有找到打標識的生命周期域,則會拋出異常:DependencyResolutionException。官方文檔解釋:Configure the component so that every dependent component or call to Resolve() within a ILifetimeScope tagged with any of the provided tags value gets the same, shared instance. Dependent components in lifetime scopes that are children of the tagged scope will share the parent's instance. If no appropriately tagged scope can be found in the hierarchy an DependencyResolutionException is thrown. 

4、InstancePerOwned

在一個生命周期域中所擁有的實例創建的生命周期中,每一個依賴組件或調用Resolve()方法創建一個單一的共享的實例,並且子生命周期域共享父生命周期域中的實例。若在繼承層級中沒有發現合適的擁有子實例的生命周期域,則拋出異常:DependencyResolutionException。官方文檔解釋:Configure the component so that every dependent component or call to Resolve() within a ILifetimeScope created by an owned instance gets the same, shared instance. Dependent components in lifetime scopes that are children of the owned instance scope will share the parent's instance. If no appropriate owned instance scope can be found in the hierarchy an DependencyResolutionException is thrown. 

5、SingleInstance

每一次依賴組件或調用Resolve()方法都會得到一個相同的共享的實例。其實就是單例模式。官方文檔解釋:Configure the component so that every dependent component or call to Resolve() gets the same, shared instance. 

6、InstancePerHttpRequest  (新版autofac建議使用InstancePerRequest)

在一次Http請求上下文中,共享一個組件實例。僅適用於asp.net mvc開發。

官方文檔解釋:Share one instance of the component within the context of a single HTTP request.

二、常用方法

(1)builder.RegisterType<Object>().As<Iobject>():注冊類型及其實例。例如下面就是注冊接口IDAL的實例SqlDAL
(2)IContainer.Resolve<IDAL>():解析某個接口的實例。例如上面的最后一行代碼就是解析IDAL的實例SqlDAL
(3)builder.RegisterType<Object>().Named<Iobject>(string name):為一個接口注冊不同的實例。有時候難免會碰到多個類映射同一個接口,比如SqlDAL和OracleDAL都實現了IDAL接口,為了准確獲取想要的類型,就必須在注冊時起名字。
(4)IContainer.ResolveNamed<IDAL>(string name):解析某個接口的“命名實例”。例如上面的最后一行代碼就是解析IDAL的命名實例OracleDAL
(5)builder.RegisterType<Object>().Keyed<Iobject>(Enum enum):以枚舉的方式為一個接口注冊不同的實例。有時候我們會將某一個接口的不同實現用枚舉來區分,而不是字符串,
(6)IContainer.ResolveKeyed<IDAL>(Enum enum):根據枚舉值解析某個接口的特定實例。例如上面的最后一行代碼就是解析IDAL的特定實例OracleDAL
(7)builder.RegisterType<Worker>().InstancePerDependency():用於控制對象的生命周期,每次加載實例時都是新建一個實例,默認就是這種方式
(8)builder.RegisterType<Worker>().SingleInstance():用於控制對象的生命周期,每次加載實例時都是返回同一個實例
(9)IContainer.Resolve<T>(NamedParameter namedParameter):在解析實例T時給其賦值

三、文件配置

通過配置的方式使用
(1)先配置好配置文件
<?xml version="1.0"?>
  <configuration>
    <configSections>
      <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
    </configSections>
    <autofac defaultAssembly="ConsoleApplication1">
      <components>
        <component type="ConsoleApplication1.SqlDAL, ConsoleApplication1" service="ConsoleApplication1.IDAL" />
      </components>
    </autofac>
  </configuration>

 

(2)讀取配置實現依賴注入(注意引入Autofac.Configuration.dll)
static void Main(string[] args)
{
    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterType<DBManager>();
    builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
    using (IContainer container = builder.Build())
    {
        DBManager manager = container.Resolve<DBManager>();
        manager.Add("INSERT INTO Persons VALUES ('Man', '25', 'WangW', 'Shanghai')");
    }

 

四、示例

 MVC5示例中實現的功能有:程序集注冊、按服務注冊、屬性注入、泛型注入

global.cs

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        InitDependency();
        StackExchange.Profiling.EntityFramework6.MiniProfilerEF6.Initialize();
    }
    private void InitDependency()
    {
        ContainerBuilder builder = new ContainerBuilder();
        Type baseType = typeof(IDependency);
        // 自動注冊當前程序集
        //builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();
        // 注冊當前程序集
        Assembly assemblies = Assembly.GetExecutingAssembly();
        builder.RegisterAssemblyTypes(assemblies)
        .Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
        .AsImplementedInterfaces().InstancePerLifetimeScope();//保證對象生命周期基於請求
        //注冊引用的程序集
        //var assemblyList = BuildManager.GetReferencedAssemblies().Cast<Assembly>().Where(assembly => assembly.GetTypes().Any(type => type.GetInterfaces().Contains(baseType)));
        //var enumerable = assemblyList as Assembly[] ?? assemblyList.ToArray();
        //if (enumerable.Any())
        //{
        //    builder.RegisterAssemblyTypes(enumerable)
        //        .Where(type => type.GetInterfaces().Contains(baseType))
        //        .AsImplementedInterfaces().InstancePerLifetimeScope();
        //}
        //注冊指定的程序集
        //自動注冊了IStudentService、IUserService
        builder.RegisterAssemblyTypes(Assembly.Load("AppService"), Assembly.Load("AppService"))
        .Where(t => t.Name.EndsWith("Service"))
        .AsImplementedInterfaces();
        //一、Type注冊服務
        builder.RegisterType<CourseService>().As<ICourseService>();
        builder.RegisterType<UserService>().AsSelf();// 注入類本身,等價於.As<UserService>();
        builder.RegisterType<ScoreManage>().AsImplementedInterfaces();//批量注冊,等價於.As<IEnglishScoreManage>().As<IMathematicsScoreManage>();
        //二、Named注冊服務
        //builder.RegisterType<ChineseScorePlusManage>().Named<IChineseScoreManage>(ChineseScoreEnum.ChineseScorePlus.ToString());// 一個接口與多個類型關聯
        //builder.RegisterType<ChineseScoreManage>().Named<IChineseScoreManage>(ChineseScoreEnum.ChineseScore.ToString());// 一個接口與多個類型關聯
        //三、Keyed注冊服務
        builder.RegisterType<ChineseScorePlusManage>().Keyed<IChineseScoreManage>(ChineseScoreEnum.ChineseScorePlus);// 一個接口與多個類型關聯
        builder.RegisterType<ChineseScoreManage>().Keyed<IChineseScoreManage>(ChineseScoreEnum.ChineseScore);// 一個接口與多個類型關聯

        //泛型注冊,可以通過容器返回List<T> 如:List<string>,List<int>等等
        //builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>)).InstancePerLifetimeScope();
        //生命周期
        //builder.RegisterType<StudentService>().As<IStudentService>().InstancePerLifetimeScope(); //基於線程或者請求的單例..就是一個請求 或者一個線程 共用一個
        //builder.RegisterType<StudentService>().As<IStudentService>().InstancePerDependency(); //服務對於每次請求都會返回單獨的實例
        //builder.RegisterType<StudentService>().As<IStudentService>().SingleInstance(); //單例.. 整個項目公用一個
        //builder.RegisterType<StudentService>().As<IStudentService>().InstancePerRequest(); //針對MVC的,或者說是ASP.NET的..每個請求單例
        builder.RegisterType<ServiceGetter>().As<IServiceGetter>();//用於一個接口與多個類型關聯
        builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();//屬性注入,未注冊將出現“沒有為該對象定義無參數的構造函數。”
        builder.RegisterType<TestDbContext>().As<IDbContext>().InstancePerLifetimeScope();
        builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();//泛型注入
        //builder.RegisterFilterProvider(); //注入特性,特性里面要用到相關的服務
        IContainer container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));//生成容器並提供給MVC
    }
    protected void Application_BeginRequest()
    {
        if (Request.IsLocal)//這里是允許本地訪問啟動監控,可不寫
        {
            MiniProfiler.Start();
        }
    }
    protected void Application_EndRequest()
    {
        MiniProfiler.Stop();
    }
}

 

控制器

public class HomeController : Controller
{
    private readonly IStudentService _studentService;
    private readonly ITeacherService _teacherService;
    private readonly IUserService _userService;
    public readonly UserService UserService;
    private readonly IEnglishScoreManage _englishScoreManage;
    private readonly IMathematicsScoreManage _mathematicsScoreManage;
    private IServiceGetter getter;
    public ICourseService CourseService
    {
        get;
        set;
    }
    private readonly IRepository<Student> _studentRrepository;
    public HomeController(IStudentService studentService, IUserService userService, ITeacherService teacherService, UserService userService1, IMathematicsScoreManage mathematicsScoreManage, IEnglishScoreManage englishScoreManage, IServiceGetter getter, IRepository<Student> studentRrepository)
    {
        _studentService = studentService;
        _userService = userService;
        _teacherService = teacherService;
        this.UserService = userService1;
        _mathematicsScoreManage = mathematicsScoreManage;
        _englishScoreManage = englishScoreManage;
        this.getter = getter;
        _studentRrepository = studentRrepository;
    }
    public ActionResult Index()
    {
        var name = "";
        var student = _studentRrepository.GetById("4b900c95-7aac-4ae6-a122-287763856601");
        if (student != null)
        {
            name = student.Name;
        }
        ViewBag.Name = _teacherService.GetName();
        ViewBag.UserName1 = _userService.GetName();
        ViewBag.UserName2 = UserService.GetName();
        ViewBag.StudentName = _studentService.GetName() + "-" + name;
        ViewBag.CourseName = CourseService.GetName();
        ViewBag.EnglishScore = _englishScoreManage.GetEnglishScore();
        ViewBag.MathematicsScore = _mathematicsScoreManage.GetMathematicsScore();
        //ViewBag.ChineseScore = getter.GetByName<IChineseScoreManage>(ChineseScoreEnum.ChineseScore.ToString()).GetScore();
        //ViewBag.ChineseScorePlus = getter.GetByName<IChineseScoreManage>(ChineseScoreEnum.ChineseScorePlus.ToString()).GetScore();
        ViewBag.ChineseScore = getter.GetByKey<ChineseScoreEnum, IChineseScoreManage>(ChineseScoreEnum.ChineseScore).GetScore();
        ViewBag.ChineseScorePlus = getter.GetByKey<ChineseScoreEnum, IChineseScoreManage>(ChineseScoreEnum.ChineseScorePlus).GetScore();
        return View();
    }
}

 

頁面

@{
    ViewBag.Title = "Home Page";
}

<div class="jumbotron">
    <h1>ASP.NET</h1> 
</div>

<div class="row">
    <div class="col-md-4">
        <h2>Teacher: @ViewBag.Name </h2>
        <p>
            CourseName: @ViewBag.CourseName
        </p>
        <p></p>
    </div>
    <div class="col-md-4">
        <h2>User</h2>
        <p>接口注入:@ViewBag.UserName1</p>
        <p>類注入:@ViewBag.UserName2</p>
    </div>
    <div class="col-md-4">
        <h2>Student: @ViewBag.StudentName</h2>
        <p>English:@ViewBag.EnglishScore</p> 
        <p>Math: @ViewBag.MathematicsScore</p> 
        <p>Chinese: @ViewBag.ChineseScore</p> 
        <p>ChinesePlus:@ViewBag.ChineseScorePlus</p> 
    </div>
</div>

 

代碼下載:https://gitee.com/zmsofts/XinCunShanNianDaiMa/blob/master/EntityFrameworkExtension.rar

注意:codefirst開發,先遷移后才能使用

 

參考文章:

https://www.cnblogs.com/struggle999/p/6986903.html

https://www.cnblogs.com/gdsblog/p/6662987.html

https://www.cnblogs.com/kissdodog/p/3611799.html

https://www.cnblogs.com/fuyujian/p/4115474.html

 http://www.cnblogs.com/tiantianle/category/779544.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM