天天看點

Autofac - 屬性注入

屬性注入不同于通過構造函數方式傳入參數. 這裡是通過注入的方式, 在類建立完畢之後, 資源釋放之前, 給屬性指派.

這裡, 我重新弄一些類來示範這一篇吧.

public class ClassA
{
    private readonly ClassB b;

    public ClassA(ClassB b)
    {
        this.b = b;
    }

    public void Show()
    {
        Console.WriteLine("I am ClassA's instance !");
    }
}

public class ClassB
{
    public ClassA A { get; set; }

    public void Show()
    {
        Console.WriteLine("I am ClassB's instance !");
    }

}

public class ClassC
{
   public string Name { get; set; }

    public ClassD D { get; set; }

    public void Show()
    {
        Console.WriteLine("I am ClassC's instance !" + Name);
    }
}

public class ClassD
{
    public void Show()
    {
        Console.WriteLine("I am ClassD's instance !");
    }
}      

1. 一般方法

var builder = new ContainerBuilder();

builder.Register(n => new ClassC { D = n.Resolve<ClassD>(), Name = "Sniper"  });
builder.RegisterType<ClassD>();

var container = builder.Build();

var c = container.Resolve<ClassC>();
c.Show();
c.D.Show();      
Autofac - 屬性注入

這種方法, 不止可以注入屬性, 還可以給字段指派

2. 反射的方式

var builder = new ContainerBuilder();

builder.RegisterType<ClassD>();
var s = builder.RegisterType<ClassC>().PropertiesAutowired();

var container = builder.Build();

var c = container.Resolve<ClassC>();
c.Show();
c.D.Show();      
Autofac - 屬性注入

這裡需要注意一點, 由于ClassC中有ClassD格式的屬性, 是以ClassD也必須要注冊一下. 為什麼呢? 來看一下源碼

Autofac - 屬性注入

PropertiesAutowired()方法裡面, 主要就是調用上圖中的方法. 會通過反射的方式擷取屬性, 然後也是通過Resolve的方式來擷取屬性的值.

注:

  仔細觀察ClassA和ClassB, 可以發現, 他們循環依賴了, 那麼如果我要得到ClassB, 怎麼辦? 嘗試下第一種方法, 你會發現, 我去, 報錯了.

  嘗試下第二種方法, 還是報錯. 那怎麼辦呢? 

var builder = new ContainerBuilder();

builder.RegisterType<ClassB>().PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies).SingleInstance();
builder.Register(n=>new ClassA(n.Resolve<ClassB>()));

var container = builder.Build();

var b = container.Resolve<ClassB>();
b.Show();
b.A.Show();      
Autofac - 屬性注入

還是通過反射的方式, 隻不過要注意一下, 傳入參數和SingleInstance, 不加, 都會報錯的.

3. 通過名稱

var builder = new ContainerBuilder();

var s = builder.RegisterType<ClassC>().WithProperty("D", new ClassD());

var container = builder.Build();

var c = container.Resolve<ClassC>();
c.Show();
c.D.Show();      
Autofac - 屬性注入

通過屬性名稱, 直接new一個執行個體給他

4. OnActivating/OnActivated 方式

此方法的執行時機, 是構造函數建立結束之後, 資源釋放之前, 是以在此期間也可以實作

var builder = new ContainerBuilder();

builder.RegisterType<ClassC>().OnActivating(e => e.Instance.D = e.Context.Resolve<ClassD>());
builder.RegisterType<ClassD>();

var container = builder.Build();

var c = container.Resolve<ClassC>();
c.Show();
c.D.Show();      

這裡的 OnActivating 也可換成 OnActivated . 實作這裡的場景, 是能得到一樣的結果的.

 參考:

   AutoFac使用方法總結

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

   Autofac文檔