快到年終了, 最近項目比較悠閑, 就想總結下, 項目中所使用到的一些技術, 以及使用方法.
之前有寫過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();
從圖上可以看出, 通過這種方式注冊類型之後, 可以正常擷取到執行個體
二、執行個體注冊
示例: (共同部分我就不貼了, 隻貼主要部分)
builder.RegisterInstance(new Person(new Dog()));
//-------------------------------------------------
var person = container.Resolve<Person>();
person.Self();
person.Say();
這裡還有一種為單例模式準備的實作, 可以把單例托管為容器單例, 我這裡就沒有寫那麼多了, 直接上了一個非單例的示例. 也是有效果的喲
builder.RegisterInstance(new Cat()).ExternallyOwned();
//-------------------------------------------------
var cat = container.Resolve<Cat>();
cat.Name = "miao";
cat.Say();
var cat1 = container.Resolve<Cat>();
cat1.Say();
這裡我後來試了一下, 就算不加那個, 得到的效果也是單例的效果
三、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注冊的位置不受限制, 在前面, 在後面, 都是不受影響的, 但是不能沒有啊, 沒有就會報錯了, 程式找不到.
四、程式集注冊
這種方式适合懶人用
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();
//-------------------------------------------------
var animal = container.Resolve<IAnimal>();
animal.Say();
我這裡面有兩個類實作了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();
如果我想要輸出Dog類咋搞呢. 使用 PreserveExistingDefaults(), 這個方法是告訴容器, 這次注冊的不是預設輸出的.
builder.RegisterType<Dog>().As<IAnimal>();
builder.RegisterType<Cat>().As<IAnimal>().PreserveExistingDefaults();
//-------------------------------------------------
var animal = container.Resolve<IAnimal>();
animal.Say();
那如果想一個接口上注冊多個類, 并且都能正常擷取呢? 那就看下一篇分解了
參考資料:
Autofac 元件、服務、自動裝配 《第二篇》
Autofac文檔