2012-10-18 51 views
2

是否有可能爲所有實現接口註冊類型? E.g,我有一個:SimpleInjector - 爲所有接口註冊一個類型

public class Bow : IWeapon 
{ 

    #region IWeapon Members 

    public string Attack() 
    { 
     return "Shooted with a bow"; 
    } 

    #endregion 
} 

public class HumanFighter 

{ 
    private readonly IWeapon weapon = null; 
    public HumanFighter(IWeapon weapon) 
    { 
     this.weapon = weapon; 
    } 

    public string Fight() 
    { 

     return this.weapon.Attack(); 
    } 

} 

    [Test] 
    public void Test2b() 
    { 
     Container container = new Container(); 
     container.RegisterSingle<Bow>(); 
     container.RegisterSingle<HumanFighter>(); 

     // this would match the IWeapon to the Bow, as it 
     // is implemented by Bow 
     var humanFighter1 = container.GetInstance<HumanFighter>(); 

     string s = humanFighter1.Fight(); 
    } 

回答

1

這完全取決於你的需求,但通常你需要使用Container的非通用註冊方法。您可以定義自己的LINQ查詢來查詢應用程序的元數據以獲取正確的類型,並使用非通用註冊方法註冊它們。這裏有一個例子:

var weaponsAssembly = typeof(Bow).Assembly; 

var registrations = 
    from type in weaponsAssembly.GetExportedTypes() 
    where type.Namespace.Contains(".Weapons") 
    from service in type.GetInterfaces() 
    select new { Service = service, Implementation = type }; 

foreach (var reg in registrations) 
{ 
    container.Register(reg.Service, reg.Implementation); 
} 

如果需要批量註冊一組實現的,基於共享的通用接口,你可以使用RegisterManyForOpenGeneric擴展方法:

// include the SimpleInjector.Extensions namespace. 

container.RegisterManyForOpenGeneric(typeof(IValidator<>), 
    typeof(IValidator<>).Assembly); 

這會尋找所有(非通用)公共類型,它們實現了IValidator<T>,並且通過它們的封閉泛型實現來註冊它們中的每一個。如果某個類型實現了多個封閉的通用版本IValidator<T>,則所有版本都將被註冊。看一看下面的例子:

interface IValidator<T> { } 
class MultiVal1 : IValidator<Customer>, IValidator<Order> { } 
class MultiVal2 : IValidator<User>, IValidator<Employee> { } 

container.RegisterManyForOpenGeneric(typeof(IValidator<>), 
    typeof(IValidator<>).Assembly); 

假設給定的接口和類定義,示出的RegisterManyForOpenGeneric登記是等效於以下手動註冊:

container.Register<IValidator<Customer>, MultiVal1>(); 
container.Register<IValidator<Order>, MultiVal1>(); 
container.Register<IValidator<User>, MultiVal2>(); 
container.Register<IValidator<Employee>, MultiVal2>(); 

這也將是容易添加方便擴展方法。就拿下面的擴展方法,它允許您註冊其所有實現的接口一個實現:

public static void RegisterAsImplementedInterfaces<TImpl>(
    this Container container) 
{ 
    foreach (var service in typeof(TImpl).GetInterfaces()) 
    { 
     container.Register(service, typeof(TImpl)); 
    } 
} 

可以使用如下:

container.RegisterAsImplementedInterfaces<Sword>(); 
+0

我想這樣做自動接線使用的組件 - 我可以通過反射來完成,但是有什麼可以自動註冊一個類型並自動將它連接到它的所有實現接口? –

+0

通用類型支持批量註冊,但不支持非通用接口。這是一個有意的設計決定。您可以詳細瞭解[這裏](http://simpleinjector.codeplex.com/wikipage?title=Advanced-scenarios#Batch_Registration)。它會告訴你爲什麼它不被支持,以及如何使用反射來做到這一點。如果您對此有任何疑問,請告訴我。我很樂意爲您提供幫助。 – Steven

+0

我已經通過反射解決了它 - 但是我想知道是否可以在本地完成,就像你可以用其他一些Ioc容器一樣。再次,這不是一個大問題,可以通過反思輕鬆實現。 –

相關問題