0

我一直有在此一展身手了一會兒沒有運氣:(使用Autofac與實現中的IDependencyResolver MVC5

當我被卡住:

我有一個MVC5 Web應用程序和我使用Autofac作爲IoC容器 基本上我有一個依賴需要我通過構造函數 傳入一個參數,但由於我通過IDependencyResolver接口解決了Autofac問題,我不允許 插入直接參數

我試圖使用委託工廠,但IM仍然得到錯誤 我敢肯定,我必須做一些錯誤....

//////////////// 
//My Interface// 
//////////////// 

public interface IConfiguration 
{ 
    string OwnerId { get; set; } 
    IDictionary<string, string> GetAllSettings(); 
    string GetSettingByKey(string SettingsKey); 
} 

/////////////////// 
//My Concrete Obj// 
/////////////////// 

public class Configuration : IConfiguration 
{ 
    public delegate Configuration Factory(string ownerId); //Added this based on what's on the Autofac Wiki - Delegate Factories 

    public string OwnerId { get; set; } 
    public Dictionary<string, string> AllSettings {get; set;} 

    public Configuration(string ownerId) { 
     //Some logic that requires ownerId 
    } 

    public IDictionary<string, string> GetAllSettings() 
    { 
     //Some other logic irrelevant for now 
    } 

    public string GetSettingByKey(string settingsKey) 
    { 
     //Some other logic irrelevant for now 
    } 
} 

/////////////////////////////////// 
//Registering Dependencies in MVC// 
/////////////////////////////////// 

var builder = new ContainerBuilder(); 
builder.RegisterType<Configuration>().As<IConfiguration>(); 

//Some other configuration 

var container = builder.Build(); 

//Set Dependency Resolver for MVC5 
DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

////////////////////////////////////////////////////////// 
//Somewhere in my MVC App where I require IConfiguration// 
////////////////////////////////////////////////////////// 

var ownerId = GetOwnerId(); 

//Where I require Help 

var config = DependencyResolver.Current.GetService<IConfiguration>(); //How do I pass in a parameter (ownerId) to my underlying autofac container? 

//I Tried this but it didn't work 
var configFactory = DependencyResolver.Current.GetService<Func<string,IConfiguration>>(); 
var config = configFactory.Invoke(ownerId); 

我得到的YSOD去了解這樣

與類型「Common.Configuration」 Autofac.Core.Activators.Reflection.DefaultConstructorFinder'裏找到的構造函數

都不能在可用的服務和參數來調用: 無法解析的構造函數的參數「System.String OWNERID」 'Void .ctor(System.String)'。

在此先感謝球員:)

+0

我需要放置一個賞金這個夥計:)? – 2014-10-09 03:53:58

+0

什麼是'ownerId'?是基於運行時條件(例如傳入請求或用戶會話)而改變的東西,還是在應用程序生命週期內(例如因爲它在配置文件中配置)而被修復的東西? – Steven 2014-10-09 06:29:11

+0

嗨史蒂文謝謝你的問題是它的東西,這是在運行時間條件下確定:)我不能把它放在配置中,因爲它還不知道... – 2014-10-09 19:34:59

回答

1

我想你可能看到這個鏈接:DependencyResolver: Pass parameters可能解決此特定情況下,你的問題

一個建議,就是做演員回AutofacDependencyResolver和調用本機從ApplicationContainer方法,這樣的事情(我不知道如果語法是正確的):

var rawContainer = (AutofacDependencyResolver)DependencyResolver.Current; 
     rawContainer.ApplicationContainer.Resolve<IConfiguration>(new[] { ownerId }); 

我沒有接取到代碼的權利,但我已經在我工作的公司看到爲Extensi在方法的IDependencyResolver包裝上面這段代碼,像這樣:

public static class AutofacHelper 
{ 
    public static T Resolve<T>(this IDependencyResolver container, Parameter[] paramsCtor = null) 
    { 
     var rawContainer = (AutofacDependencyResolver) DependencyResolver.Current; 
     return rawContainer.ApplicationContainer.Resolve<T>((IEnumerable<Parameter>) paramsCtor); 
    } 
} 

,然後就可以正常調用它通過DependencyResolver.Current

+0

您可以使用'AutofacDependencyResolver.Current'來避免投射。 – 2014-10-09 17:12:33

+0

謝謝你們,我給了它一個破解,真的,我從來沒有想過要把它還給/還是不知道特拉維斯是怎麼解決的......我給它一個鏡頭,讓你們知道歡呼吧... – 2014-10-09 19:38:00

+0

是的,這是實際上我發現的帖子我試圖想出解決方案... @Peter Lillevold可能仍然能夠幫助我? – 2014-10-09 22:29:30

1

煩惱都造成的,因爲你的行爲混合運行時數據。您不應該將運行時數據(您的ownerId是運行時數據)注入到應用程序的組件中。您的應用程序組件應該僅依賴於其他組件。混合各種各樣的麻煩。例如,它使驗證對象圖更加困難。

因此,不要在構造函數中注入運行時數據,而應注入允許在構建對象圖後檢索該運行時值的服務。你的情況我能想象一個IOwnerContext抽象的存在:

public interface IOwnerContext 
{ 
    string CurrentOwnerId { get; } 
} 

這怎麼所有者ID檢索取決於你正在運行的應用程序。例如,你可以想象有一個後臺服務運行在你的業務邏輯之上,它有一個IOwnerContext實現,它返回基於某個正在處理的消息的值,或者基於某個配置值。

在Web應用程序的情況下,你可能會從當前請求檢索數據和這個邏輯應該放在這個特定應用的實現:

public class AspNetOwnerContext : IOwnerContext 
{ 
    public string CurrentOwnerId 
    { 
     get 
     { 
      string host = HttpContext.Current.Request.Url.Host; 
      int index = host.IndexOf("."); 
      string subdomain = host.Substring(0, index); 
      return subdomain; 
     } 
    } 
} 
+0

呵呵我真的有那個接口,我只是決定不把它放在(我通過放置該var ownerId = GetOwerId();)來削減代碼,因爲我認爲我會膨脹這個例子(對於我試圖解決的實際問題),但是您提到這個問題的好處讓我覺得自己走上了正確的道路我的接口被稱爲IConfigOwner,它只有一個目的GetOwnerId():)我喜歡你如何提到不混合運行時數據與行爲。我正在做你剛剛提到的;具體實現該接口的類...關於我的特定問題的任何想法? – 2014-10-09 22:46:06

+0

@EgliBecerra:您應該將'IConfigOwner'注入到'Configuration'類中,這應該可以解決您的問題。 – Steven 2014-10-09 22:48:23