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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Autofac之类型注册

發(fā)布時間:2023/12/15 综合教程 40 生活家
生活随笔 收集整理的這篇文章主要介紹了 Autofac之类型注册 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本次主要學(xué)習(xí)一下Autofac中實(shí)現(xiàn)類型注冊的幾種方式,這里并不打算一開始就從基于接口開發(fā)的服務(wù)關(guān)聯(lián)切入,而是先從一個簡單的類型注冊來學(xué)起,雖然實(shí)際開發(fā)中可能不會這么做,但是個人感覺從這里學(xué)起理解能能更加深刻

Autofac使用流程

按照Ioc(控制反轉(zhuǎn))的思想構(gòu)建你的應(yīng)用
添加Autofac引用
創(chuàng)建ContainerBuilder
注冊組件
創(chuàng)建容器,將其保存以備后續(xù)使用
應(yīng)用程序運(yùn)行階段
從容器中創(chuàng)建一個生命周期
在此生命周期作用域內(nèi)解析組件實(shí)例

nuget添加Autofac引用

測試代碼

這里提供一個很簡單的類作為測試

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

創(chuàng)建容器

所有的Ioc框架都是類似的,它們的目的都是將類的實(shí)例化和調(diào)用解耦,調(diào)用者不再直接創(chuàng)建被調(diào)用者的實(shí)例,而是交由容器創(chuàng)建,只是在實(shí)現(xiàn)上有各自不同的方式

var builder = new ContainerBuilder();

普通注冊

泛型注冊:RegisterType<T>()

注冊的類型必須在當(dāng)前項(xiàng)目或被當(dāng)前項(xiàng)目引用,因?yàn)槭褂梅盒停仨氼愋兔鞔_

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

通過Type對象進(jìn)行注冊:RegisterType(Type)

被注冊的類型可以不是被直接引用,但類型所在的程序集必須被加載,這種注冊方式在有插件或類似需要動態(tài)加載程序集的情況下使用,通過掃描程序集,獲取一些滿足指定條件的類型,來進(jìn)行注冊。

通過在項(xiàng)目中引用CSharp.Tests.Model實(shí)現(xiàn)

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也可以實(shí)現(xiàn)注冊,但是如何將類型作為Resolve<T>泛型類型參數(shù)暫時不知道

lambda表達(dá)式注冊

之前的方式都是通過類型進(jìn)行直接注冊的,這種注冊方式,在獲取時,會直接通過構(gòu)造函數(shù)new出對象,不會做更多的操作。有時我們希望能夠在獲取對象時能夠自動的做更多的事情時,我們可以通過lambda注冊來解決,在lambda表達(dá)式中可以做很多事,包括一些屬性注入、方法注入、條件判斷等等

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

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

實(shí)例注冊

通過RegisterInstance進(jìn)行實(shí)例注冊,進(jìn)行實(shí)例注冊時,需要注意,實(shí)例注冊可以作為一種單例注冊的方式,也就是在后面通過Autofac獲取SqlDal對象時,獲取到的是注冊時的那個對象。并且,如果一個在某處修改了該對象,其他地方再獲取時,獲取到的就是修改后的對象

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

泛型注冊

通過RegisterGeneric() 這個方法實(shí)現(xiàn)泛型注冊,在容器中可以創(chuàng)建出泛型的具體對象

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

Module注冊

在日常開發(fā)中,可能不同開發(fā)會負(fù)責(zé)不同的模塊進(jìn)行單獨(dú)開發(fā)。在開發(fā)過程中,不同模塊不同開發(fā)可能都有自己的類型需要注冊到autofac中,但是如果每個人在注冊時,都去修改一個指定地方的代碼,這在進(jìn)行代碼合并時,是令人痛苦的。更好的方式是,每個開發(fā)不同的模塊都有自己指定的類型注冊區(qū)域,這樣,在代碼合并時,會減少很多代碼沖突

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進(jìn)行注冊。

通過這種方式,不同的開發(fā)就可以各自創(chuàng)建一個類繼承自Module,然后重寫Load方法,在Load方法進(jìn)行自己的類型注冊,最后再進(jìn)行Module的統(tǒng)一注冊(這里還可以通過自定義實(shí)現(xiàn)了IModule接口的類型,然后在RegisterModule時傳入來達(dá)到同樣的效果并且功能也更多)

默認(rèn)的注冊

如果一個類型被多次注冊,以最后注冊的為準(zhǔn)。通過使用PreserveExistingDefaults() 修飾符,可以指定某個注冊為非默認(rèn)值。

批量注冊、程序集注冊

上面的例子中都是將單個類型注冊到容器中,而在實(shí)際開發(fā)中可能存在多個類型需要注冊,難道要每個類型挨個注冊嗎?Autofac中為這種情況提供了程序集注冊的方式

程序集批量注冊

類型注冊中提到了通過掃描程序集,來獲取部分類型進(jìn)行注冊。Autofac對此提供了一個方便的方式,可以直接通過程序集來篩選類型注冊

//獲取當(dāng)前應(yīng)用程序加載程序集(C/S應(yīng)用中使用)
var assembly = Assembly.GetExecutingAssembly();
//注冊所有程序集類定義的非靜態(tài)類型
builder.RegisterAssemblyTypes(assembly);

程序集過濾后批量注冊

上面的方式達(dá)到了批量的效果,但是通常并不需要把所有的類型都進(jìn)行注冊,所以Autofac提供了幾種過濾方式

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

排除指定類型的注冊

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

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

程序集Module注冊

Module注冊,為多人開發(fā)提供了一種方便的注冊方式,但是也可以發(fā)現(xiàn),這種方式,還是會需要手動注冊Module,如果Module過多,Module注冊代碼也會顯得多而雜,當(dāng)然,可以通過人工管理來控制Module的量。但是Autofac還提供了一種更方便的方式,并且,對于類似Orchard的模塊開發(fā)(子模塊與主模塊無引用關(guān)系,通過程序集加載方式來加載子模塊)或是插件開發(fā),我們沒辦法通過Registerodule來注冊無直接引用關(guān)系的Module

var assembly = Assembly.GetExecutingAssembly();
//注冊assembly程序集中所有實(shí)現(xiàn)了IModule接口的類型(多層繼承也算),這樣只需要取出所有程序集,然后通過RegisterAssemblyModules進(jìn)行一次性注冊,就可以自動注冊所有Module了
builder.RegisterAssemblyModules(assembly);            
builder.RegisterAssemblyModules<SqlModule>(assembly);//指定泛型類型只注冊assembly程序集中繼承自SqlModule的Module

被注冊的類型需要在指定類的命名空間中

var assembly = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(assembly).InNamespaceOf<AutofacTest>();

總結(jié)

以上是生活随笔為你收集整理的Autofac之类型注册的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。