我正在將項目從MEF轉換到Simple Injector,在MEF中他們有一個調用,您可以在其中註冊從接口派生的所有類型以及所有類型實現的接口用Simple Injector註冊所有實現的接口
conventions.TypesDerivedFrom<T>()
.ExportInterfaces()
在簡單的注射器I可以註冊所有從有RegisterCollection
呼叫的接口派生的類型,但這不註冊所有類型實現的接口。該方案的基本例子中,我追求
public interface IAnimal { }
public interface IDomesticAnimal { }
public interface ICat { }
public interface IDog { }
public class Cat : IAnimal, IDomesticAnimal, ICat { }
public class Dog : IAnimal, IDomesticAnimal, IDog { }
public void TestFunctionality()
{
var container = new Container();
Assembly[] assemblies = new [] { typeof(IAnimal).Assembly };
// container.RegisterCollection<IAnimal>(assemblies) --> Register only IAnimal
container.RegisterCollectionAndRelatedInterfaces<IAnimal>(assemblies);
container.Register<AnimalShelter>();
container.Register<AnimalPlayground>();
// container.Verify() --> This would fail
}
public class AnimalShelter
{
public AnimalShelter(IEnumerable<IDomesticAnimal> animals) {}
public void Feed() {}
}
public class AnimalPlayground
{
public AnimalPlayground(AnimalShelter animalShelter, ICat cat, IDog dog) {}
}
此拋出一個異常,因爲ICat
doesn't已註冊的類型。爲了解決這個問題我已經實現的擴展方法
public static void RegisterCollectionAndRelatedInterfaces<T>(this Container container,
IEnumerable<Assembly> assemblies)
{
HashSet<Type> interfacesToRegister = new HashSet<Type>();
var typesInterfaces = from type in container.GetTypesToRegister(typeof(T), assemblies)
where type.GetInterfaces().Any()
select new { Service = type.GetInterfaces() };
foreach (var i in typesInterfaces)
{
interfacesToRegister.UnionWith(i.Service);
}
foreach (var i in interfacesToRegister)
{
var typesToRegister = container.GetTypesToRegister(i, assemblies);
if (typesToRegister.Count() == 1)
{
container.Register(i, typesToRegister.Single());
}
else if (typesToRegister.Count() != 0)
{
container.RegisterCollection(i, typesToRegister);
}
}
}
這個擴展方法有需要提醒的是,如果該類型已註冊它會拋出一個異常,如果不與override
選項創建的容器。我試圖解決這個問題,其中沿着
線條的東西,但是好像我不能讓所有的註冊類型
總的來說,我沒有溫暖的感覺對整個過程,我覺得我缺少一些東西
有沒有更好的方法來實現這個功能?
編輯
UML description of the scenario
我有這樣的設計下,在我的系統大約30具體類
我想要檢索相同的具體類型每次我要求InterfaceA
,InterfaceB
或InterfaceC
container.GetAllInstances<InterfaceA> // Should return all concreteA...Z classes
// Not all my concrete classes implement InterfaceB
container.GetAllInstances<InterfaceB> // Should return all concreteA...K classes (the same ones as above)
container.GetInstance<InterfaceC> // Should return only concreteA
這是我目前在做
container.RegisterCollection(typeof(InterfaceA),assemblies, Lifestyle.Singleton)
container.RegisterCollection(typeof(InterfaceB),assemblies, Lifestyle.Singleton)
和擴展方法
public static void RegisterCollection(this Container container, Type type, IEnumerable<Assembly> assemblies, Lifestyle lifestyle)
{
var types = container.GetTypesToRegister(type, assemblies);
// Exception when registering the same types for a second time???
var registrations = (from t in types
select lifestyle.CreateRegistration(t, container)).ToArray();
foreach (var r in registrations)
{
container.AppendToCollection(type, r);
}
}
我期待一個例外,當我去註冊相同類型InterfaceB
......但沒了
我還沒有想出如何對每個InterfaceC
進行批量註冊,這是針對具體類別的一對一關係
foreach (var type in types) { container.Register(type.GetInterfaces().Single(i => i.EndsWith(type.Name)), type); }
我不wan't依賴於類的實際名稱。
我不能完全掌握你所要完成的是什麼。我不明白爲什麼你想要(或者爲什麼甚至可以工作)在集合中只有一個元素的情況下使用'Register',當你有0或多個元素時使用'RegisterCollection'。抽象通常是 - 集合中的一對一映射 - 或 - 部分。即使你已經確定它是一個集合的一部分,你也不太可能僅僅因爲只有一個註冊而註冊這種類型的一對一(即Register)。這就是爲什麼簡單的噴油器,使一個-to-one和一個一對多的區分明確 – Steven
這將是很好,如果你可以更新你的問題和替換的應用程序的抽象實際名稱那些動物抽象,並展示如何將這些的一些用法抽象被使用(例如,你在哪裏注入一個抽樣,並在哪裏注入一個集合)。 – Steven
試圖更新代碼示例。 ''IDidentAnimal'''必須註冊爲集合,'''ICat''''''''''作爲一對一的映射。所有這些只需要註冊從'''IAnimal'''派生的類型 – TMiNus