快到年終了, 最近項目比較悠閑, 就想總結下, 項目中所使用到的一些技術, 以及使用方法.
之前有寫過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();

那如果想一個接口上注冊多個類, 并且都能正常獲取呢? 那就看下一篇分解了
參考資料:
文章列表
