2016-12-02 66 views
1

有兩個項目的解決方案,我遇到了DI問題。 該解決方案由一個類庫和一個WebApi2應用程序(它使用類庫並公開api)組成。類庫中的依賴注入

我在類庫中定義了一個Autofac.module,它在項目中設置了所有的DI。

在WebApi2項目中,我創建了DI容器(使用Autofac.WebApi2)並從類庫中加載模塊。現在,當WepApi2項目中的api控制器請求類庫中的服務時,它們會創建所有依賴項,這一切都很好!

問題是,我現在在類庫中需要從一個字符串(最終來自數據庫)實例化一些類,據我所知,通過使用反射來做到這一點的唯一方法,所以我做像這樣:

var ruleType = Type.GetType(rule.RuleImplementation.Implementation); 
var rule = (IRule)Activator.CreateInstance(ruleType,param1,param2); 

的問題是,實現的iRule接口的類也有這需要得到解決的依賴,這是什麼讓我敲我的我的鍵盤了,而在現在。

是否有可能以某種方式使用反射和autoFac一起實例化對象?我仍然需要能夠將參數傳遞給對象。

...或者有沒有辦法以某種方式訪問​​容器(它是在webApi2程序集中創建的)並使用它來解決它?我想這應該是某種服務模式,我認爲這是一種反模式。

我該如何繼續?所有的輸入是非常讚賞。

回答

2

使用Activator.CreateInstance創建組件是個壞主意,因爲它基本上意味着您正在重新實現容器爲您執行的邏輯,但沒有DI庫爲您提供的功能和安全防護。

我在類庫中定義了一個Autofac.module,它在項目中設置了所有的DI。

這是你麻煩的根源所在。在應用程序中應該只有一個地方組成對象圖(並註冊),這是應用程序的Composition Root。雖然組合根(層)和表示層都駐留在同一個項目中很常見,但此組合根可以被看作位於表示層(Web API)之上的獨立層。

這樣做會消除這個問題,因爲在你的組合根目錄中你已經有權訪問容器。

一個允許使用來自數據庫的定義創建規則的好方法是定義一個IRuleActivator抽象。該抽象可以在您的庫中定義並在組合根內部實現。這使得實現包裝容器,而庫保持渾然不覺容器的存在:

// Defined in the library 
public interface IRuleActivator 
{ 
    IRule GetRule(RuleData rule); 
} 

// Defined in the Compostion Root 
public sealed class AutofacRuleActivator : IRuleActivator 
{ 
    private readonly IComponentContext context; 
    public AutofacRuleActivator(IComponentContext context) { 
     this.context = context; 
    } 

    public IRule GetRule(RuleData rule) { 
     Type ruleType = Type.GetType(rule.RuleImplementation.Implementation); 
     return (IRule)this.context.Resolve(ruleType); 
    } 
} 
1

您可以創建工廠的iRule創建:

public IRuleFactory 
{ 
    IRule CreateRule(params); 
} 

對於參數我會用一些去可以注入到實現IRuleFactory中的那種IParamsProviders,RuleImpl只是您實現的對象構造,也可以反映出來:

public class RuleFactory : IRuleFactory 
{ 
    public RuleFactory(IParamsProvider provider) 
    { 
     ... 
    } 

    public IRule CreateRule() 
    { 
     return new RuleImpl(provider.Param1, provider.Param2); 
    } 
} 

將這些接口註冊到Ioc中並將它們注入到服務處理程序中。

+0

我喜歡這個解決方案。據我所見,唯一的缺點是我必須將所有規則注入到服務中,而不管是否需要,因爲我首先知道在運行時查詢數據庫。 – iCediCe