天天看點

Autofac - 元件

快到年終了, 最近項目比較悠閑, 就想總結下, 項目中所使用到的一些技術, 以及使用方法.

之前有寫過Dapper以及Dapper的一個擴充, 這些也是項目中使用過的. 算是一個溫故而知新吧.

代碼:

public interface IAnimal
{
    void Say();
}

public class Dog : IAnimal
{
    public string Name { get; set; }
    public void Say()
    {
        Console.WriteLine("汪汪汪!");
        if (!string.IsNullOrEmpty(Name))
        {
            Console.WriteLine("此汪名叫 " + Name);
        }
    }
}

public class Cat : IAnimal
{
    public string Name { get; set; }
    public void Say()
    {
        Console.WriteLine("喵喵喵!");
        if (!string.IsNullOrEmpty(Name))
        {
            Console.WriteLine("此喵名叫 " + Name);
        }
    }
}

public class Person
{
    IAnimal adopt;

    public Person()  { }

    public void Self()
    {
        Console.WriteLine("我是主人");
    }

    public Person(IAnimal MyPerson)
    {
        adopt = MyPerson;
    }

    public void Say()
    {
        Console.WriteLine("我領養了一隻小動物");
        adopt.Say();
    }
}      

 一、類型注冊

類型的注冊, 使用的方法是container.Resolve<Type>()和container.Resolve(typeof(Type))兩個方法.

示例:

var builder = new ContainerBuilder();

builder.RegisterType<Person>();
builder.RegisterType<Dog>().As<IAnimal>();
builder.RegisterType(typeof(Cat));

var container =  builder.Build();

var person = container.Resolve<Person>();
person.Self();
Console.WriteLine("---------");
var animal = container.Resolve<IAnimal>();
animal.Say();
Console.WriteLine("---------");
var cat = container.Resolve<Cat>();
cat.Say();      
Autofac - 元件

從圖上可以看出, 通過這種方式注冊類型之後, 可以正常擷取到執行個體

二、執行個體注冊

示例: (共同部分我就不貼了, 隻貼主要部分)

builder.RegisterInstance(new Person(new Dog()));

//-------------------------------------------------
var person = container.Resolve<Person>();
person.Self();
person.Say();      
Autofac - 元件

這裡還有一種為單例模式準備的實作, 可以把單例托管為容器單例, 我這裡就沒有寫那麼多了, 直接上了一個非單例的示例. 也是有效果的喲

builder.RegisterInstance(new Cat()).ExternallyOwned();

//-------------------------------------------------
var cat = container.Resolve<Cat>();
cat.Name = "miao";
cat.Say();

var cat1 = container.Resolve<Cat>();
cat1.Say();      
Autofac - 元件

這裡我後來試了一下, 就算不加那個, 得到的效果也是單例的效果 

 三、Lambda方式注冊 

//builder.RegisterType<Dog>().As<IAnimal>();
builder.Register(c => new Person(c.Resolve<IAnimal>()));
builder.RegisterType<Dog>().As<IAnimal>();

//-------------------------------------------------
var person = container.Resolve<Person>();
person.Say();      

IAnimal注冊的位置不受限制, 在前面, 在後面, 都是不受影響的, 但是不能沒有啊, 沒有就會報錯了, 程式找不到.

Autofac - 元件

四、程式集注冊

這種方式适合懶人用

builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();

//-------------------------------------------------
var animal = container.Resolve<IAnimal>();
animal.Say();      
Autofac - 元件

我這裡面有兩個類實作了IAnimal接口, 但是為什麼這裡擷取到的是cat類, 而不是dog類呢?

五、泛型注冊

builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>)).InstancePerLifetimeScope();
var container = builder.Build();
//-------------------------------------------------
IList<Dog> dogs = container.Resolve<IList<Dog>>();      

這裡擷取到的dogs是一個空的集合, 并不是null值.

六、預設注冊

如果一個類, 被多次注冊, 會以最後一次注冊為準, 就想上面 "四" 出現的情況, 隻輸出了"喵喵喵", 那是因為Dog類先注冊, Cat類後注冊, 把之前的覆寫掉了. 注意, 覆寫并不是沒有了, 隻是不能通過這種方式擷取了而已, 還是可以通過别的方式來擷取你想要的類的.

先看一下效果:

builder.RegisterType<Dog>().As<IAnimal>();
builder.RegisterType<Cat>().As<IAnimal>();

//-------------------------------------------------
var animal = container.Resolve<IAnimal>();
animal.Say();      
Autofac - 元件

如果我想要輸出Dog類咋搞呢. 使用 PreserveExistingDefaults(), 這個方法是告訴容器, 這次注冊的不是預設輸出的.

builder.RegisterType<Dog>().As<IAnimal>();
builder.RegisterType<Cat>().As<IAnimal>().PreserveExistingDefaults();
//-------------------------------------------------
var animal = container.Resolve<IAnimal>();
animal.Say();      
Autofac - 元件

 那如果想一個接口上注冊多個類, 并且都能正常擷取呢? 那就看下一篇分解了

 參考資料:

Autofac 元件、服務、自動裝配 《第二篇》

Autofac文檔