Autofac之類型註冊

本次主要學習一下Autofac中實現類型註冊的幾種方式,這裏並不打算一開始就從基於接口開發的服務關聯切入,而是先從一個簡單的類型註冊來學起,雖然實際開發中可能不會這麼作,可是我的感受從這裏學起理解能能更加深入mysql

Autofac使用流程

  • 按照Ioc(控制反轉)的思想構建你的應用
  • 添加Autofac引用
  • 建立ContainerBuilder
  • 註冊組件
  • 建立容器,將其保存以備後續使用
  • 應用程序運行階段
  • 從容器中建立一個生命週期
  • 在今生命週期做用域內解析組件實例

nuget添加Autofac引用

測試代碼

這裏提供一個很簡單的類做爲測試sql

class SqlDal
{
    public void Add()
    {
        Console.WriteLine("向數據庫寫入一條數據");
    }
}

建立容器數據庫

全部的Ioc框架都是相似的,它們的目的都是將類的實例化和調用解耦,調用者再也不直接建立被調用者的實例,而是交由容器建立,只是在實現上有各自不一樣的方式框架

var builder = new ContainerBuilder();

普通註冊

泛型註冊:RegisterType<T>()ide

註冊的類型必須在當前項目或被當前項目引用,由於使用泛型,必須類型明確函數

//將SqlDal類註冊到容器中
builder.RegisterType<SqlDal>();
//經過Resolve()方法獲取註冊類型的實例,不推薦這種方式獲取,這裏的代碼只做爲測試
using (var container = builder.Build())
{               
    var sqlDal = container.Resolve<SqlDal>();
    sqlDal.Add();
}

經過Type對象進行註冊:RegisterType(Type) 學習

被註冊的類型能夠不是被直接引用,但類型所在的程序集必須被加載,這種註冊方式在有插件或相似須要動態加載程序集的狀況下使用,經過掃描程序集,獲取一些知足指定條件的類型,來進行註冊。測試

經過在項目中引用CSharp.Tests.Model實現ui

Assembly assembly = Assembly.Load("CSharp.Tests.Model");
var type = assembly.GetType("CSharp.Tests.Model.AutofacTestModel");
builder.RegisterType(type);
using (var container = builder.Build())
{
    var model = container.Resolve<AutofacTestModel>();
    Console.WriteLine(model.SayHello());               
}

TODO:將dll拷貝到bin目錄下不用引用dll也能夠實現註冊,可是如何將類型做爲Resolve<T>泛型類型參數暫時不知道spa

lambda表達式註冊

以前的方式都是經過類型進行直接註冊的,這種註冊方式,在獲取時,會直接經過構造函數new出對象,不會作更多的操做。有時咱們但願可以在獲取對象時可以自動的作更多的事情時,咱們能夠經過lambda註冊來解決,在lambda表達式中能夠作不少事,包括一些屬性注入、方法注入、條件判斷等等

class SqlDal
{
    public string Str { get; set; }

    public void Add()
    {
        Console.WriteLine("向SqlServer數據庫寫入一條數據,Str={0}", Str);
    }
}
builder.Register(type =>
{
    //經過lambda表達式註冊時添加屬性值
    var sqlDal = new SqlDal();         
    sqlDal.Str = "Test";
    return sqlDal;
});

實例註冊

經過RegisterInstance進行實例註冊,進行實例註冊時,須要注意,實例註冊能夠做爲一種單例註冊的方式,也就是在後面經過Autofac獲取SqlDal對象時,獲取到的是註冊時的那個對象。而且,若是一個在某處修改了該對象,其餘地方再獲取時,獲取到的就是修改後的對象

builder.RegisterInstance(new SqlDal());
using (var container = builder.Build())
{
    var sqlDal = container.Resolve<SqlDal>();
    sqlDal.Add();
}

泛型註冊

經過RegisterGeneric() 這個方法實現泛型註冊,在容器中能夠建立出泛型的具體對象

builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>)).InstancePerLifetimeScope();
using (IContainer container = builder.Build())
{
    var ListString = container.Resolve<IList<string>>();
}

Module註冊

在平常開發中,可能不一樣開發會負責不一樣的模塊進行單獨開發。在開發過程當中,不一樣模塊不一樣開發可能都有本身的類型須要註冊到autofac中,可是若是每一個人在註冊時,都去修改一個指定地方的代碼,這在進行代碼合併時,是使人痛苦的。更好的方式是,每一個開發不一樣的模塊都有本身指定的類型註冊區域,這樣,在代碼合併時,會減小不少代碼衝突

class SqlModule : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<SqlDal>();
    }
}
class MySqlModule : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<MySqlDal>();
    }
}
builder.RegisterModule<SqlModule>();            
builder.RegisterModule<MySqlModule>();
using (var container = builder.Build())
{
    var sqldal = container.Resolve<SqlDal>();
    sqldal.Add();
    var mysqldal = container.Resolve<MySqlDal>();
    mysqldal.Add();
}

上述代碼中,有兩個繼承自Module類的類:SqlModule、MySqlModule,這兩個類型重寫了父類的Load方法,並在load方法中,分別註冊了SqlDal與MySqlDal類型。而後在主程序中,經過RegisterModule對Module進行註冊。

經過這種方式,不一樣的開發就能夠各自建立一個類繼承自Module,而後重寫Load方法,在Load方法進行本身的類型註冊,最後再進行Module的統一註冊(這裏還能夠經過自定義實現了IModule接口的類型,而後在RegisterModule時傳入來達到一樣的效果而且功能也更多)

默認的註冊 

若是一個類型被屢次註冊,以最後註冊的爲準。經過使用PreserveExistingDefaults() 修飾符,能夠指定某個註冊爲非默認值。

批量註冊、程序集註冊

上面的例子中都是將單個類型註冊到容器中,而在實際開發中可能存在多個類型須要註冊,難道要每一個類型挨個註冊嗎?Autofac中爲這種狀況提供了程序集註冊的方式

程序集批量註冊

類型註冊中提到了經過掃描程序集,來獲取部分類型進行註冊。Autofac對此提供了一個方便的方式,能夠直接經過程序集來篩選類型註冊

//獲取當前應用程序加載程序集(C/S應用中使用)
var assembly = Assembly.GetExecutingAssembly();
//註冊全部程序集類定義的非靜態類型
builder.RegisterAssemblyTypes(assembly);

 程序集過濾後批量註冊

上面的方式達到了批量的效果,可是一般並不須要把全部的類型都進行註冊,因此Autofac提供了幾種過濾方式

builder.RegisterAssemblyTypes(assembly).Where(type => type.Namespace.Equals("CSharp.Tests.框架學習"));

 排除指定類型的註冊

使用Except排除指定類型的註冊

  builder.RegisterAssemblyTypes(assembly).Where(type => type.Namespace.Contains("CSharp.Tests")).Except<CSharp.Tests.設計思想.SqlDal>();

程序集Module註冊

Module註冊,爲多人開發提供了一種方便的註冊方式,可是也能夠發現,這種方式,仍是會須要手動註冊Module,若是Module過多,Module註冊代碼也會顯得多而雜,固然,能夠經過人工管理來控制Module的量。可是Autofac還提供了一種更方便的方式,而且,對於相似Orchard的模塊開發(子模塊與主模塊無引用關係,經過程序集加載方式來加載子模塊)或是插件開發,咱們沒辦法經過Registerodule來註冊無直接引用關係的Module

var assembly = Assembly.GetExecutingAssembly();
//註冊assembly程序集中全部實現了IModule接口的類型(多層繼承也算),這樣只須要取出全部程序集,而後經過RegisterAssemblyModules進行一次性註冊,就能夠自動註冊全部Module了
builder.RegisterAssemblyModules(assembly); builder.RegisterAssemblyModules<SqlModule>(assembly);//指定泛型類型只註冊assembly程序集中繼承自SqlModule的Module 

被註冊的類型須要在指定類的命名空間中

var assembly = Assembly.GetExecutingAssembly();builder.RegisterAssemblyTypes(assembly).InNamespaceOf<AutofacTest>();
相關文章
相關標籤/搜索