我仔細看了一下RegisterTypes,它接受了一個Func類型的參數,您可以使用它來爲每個實例提供名稱。沒有必要創建一個擴展來實現這一點。在創建屬性後,很容易爲要在容器中註冊的每個實例提供特定的名稱。
首先創建屬性類:
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class UnityNamedInstanceAttribute : Attribute
{
private readonly string instanceName;
public UnityNamedInstanceAttribute(string instanceName)
{
this.instanceName = instanceName;
}
public string InstanceName
{
get { return this.instanceName; }
}
}
然後成立專班,以幫助解決實例的名稱:
public static class UnityNamedInstance
{
public static string AttributeName(Type type)
{
var namedAttribute = type
.GetCustomAttributes(typeof(UnityNamedInstanceAttribute), true)
.FirstOrDefault()
as UnityNamedInstanceAttribute;
return namedAttribute != null ? namedAttribute.InstanceName : null;
}
public static string AttributeNameOrDefault(Type type)
{
return UnityNamedInstance.AttributeName(type) ?? WithName.Default(type);
}
}
使用我們ealier創建的屬性聲明你的測試類:
public interface ITest
{
void DebugName();
}
[UnityNamedInstance("Test A")]
public class TestA : ITest
{
#region ITest Members
public void DebugName()
{
Debug.WriteLine("This is TestA");
}
#endregion
}
[UnityNamedInstance("Test B")]
public class TestB : ITest
{
#region ITest Members
public void DebugName()
{
Debug.WriteLine("This is TestB");
}
#endregion
}
[UnityNamedInstance("Test C")]
public class TestC : ITest
{
#region ITest Members
public void DebugName()
{
Debug.WriteLine("This is TestC");
}
#endregion
}
並按常規方法將您的註冊更改爲:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().Where(t => t.Namespace == "DependencyInjectionExample.Test"),
WithMappings.FromAllInterfaces, // This way you have the same instance for each interface the class implements
UnityNamedInstance.AttributeNameOrDefault, // Use our helper to solve the name of the instance
WithLifetime.ContainerControlled);
或者你可以只避免創建屬性和輔助並命名類名後的實例,如下所示:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().Where(t => t.Namespace == "DependencyInjectionExample.Test"),
WithMappings.FromAllInterfaces,
WithName.TypeName, // Use the type name for the instances
WithLifetime.ContainerControlled);
現在你可以使用傳遞給名稱訪問每個類實例在類聲明的屬性構造函數或類名:
// Access each instance using the name you gave in the attribute
container.Resolve<ITest>("Test A").DebugName();
container.Resolve<ITest>("Test B").DebugName();
container.Resolve<ITest>("Test C").DebugName();
如果你想所有註冊的情況下,實現一個特定的接口得到:
foreach (var test in container.Resolve<ITest[]>()) {
test.DebugName();
}
OR
foreach (var test in container.ResolveAll<ITest>()) {
test.DebugName();
}
我非常有興趣知道這是否符合您的需求。感謝您的反饋!
如果仔細觀察,您會看到只有具體的類在容器中註冊。在容器中註冊的唯一接口是默認的IUnityContainer引用。你在這些類中實現接口嗎(TestClass1等)?另外,你不能在同一個接口上註冊多個類,所以如果你在這三個TestClasses中實現ITestable,它將不起作用。發佈容器中註冊的類的代碼,以便我們更好地瞭解發生了什麼。 –
如果我只能爲一個接口註冊一個類,那麼有什麼意義?我希望能夠將實現接口的類添加到名稱空間,然後自動解決它們。例如通過獲取具體類的列表。 – barto90
這就是爲什麼你有一個用名字註冊每個接口的方法。如果你想爲一個接口有3個不同的實例,那麼你必須使用該方法手動註冊每個實例。對不起,但這是你實現你想要的唯一方法。 _你可能想看看MEF_。它隨框架一起提供,我認爲它支持您需要的所有功能。 –