2013-01-09 70 views
1

我們有一個使用Ninject for DI的ASP.NET Web API應用程序。這適用於完美的使用。我們正在考慮的改進之一是能夠根據某種唯一標識符爲每個請求交換部分功能。每個請求熱插拔綁定

例子。兩位客戶使用我們的寧靜api。兩者都獲得相同的功能。第三個客戶已經支付了我們api的超級版本。他提出請求,我們加載超級DLL並將超級實現綁定到標準接口。

本質上,我期望看到的是我們可以加載DLL並使用Web API和Ninject爲每個請求換出綁定。

編輯:

所以兩個答案都對原來的問題正確的,但我的目的是不同的,這是我的不正確解釋它的錯。我們擁有的是每個人都能獲得的基礎功能層。除此之外,我們還可以根據每個客戶實施自定義邏輯來覆蓋此功能。此邏輯作爲DLL存儲在Azure Blob存儲中。

我們想要做的是,當客戶發出請求時,請去獲取DLL,綁定所有自定義服務,然後使用這些新綁定來處理請求。

熱交換不是最好的方法嗎?我們已經足夠新的注入,所以這可能是一種常見的事情,以與我們正在考慮的方式不同的方式實施。

到了某種程度,我們希望能夠以每個客戶爲基礎爲自定義綁定服務。

編輯2:

我們使用的項目條件裝幀我們知道,我們有備用的實現,但在上述情況下,直到我們得到的客戶信息和掃描,我們不知道,如果我們有備用綁定的DLL。我們甚至不知道是否有一個DLL。

我們想這樣做,所以我們可以放下文件而不是在項目中引用它。

回答

2

我不介意,你可以每次請求換出綁定。但是你可以做的是使用條件綁定。

實施例 - 缺省綁定:

protected override Ninject.IKernel CreateKernel() 
{ 
    var kernel = new StandardKernel(); 

    kernel.Bind<IAuthorizationService>() 
     .To<AuthorizationService>() 
     .InRequestScope(); 

    kernel.Bind<IService>() 
     .To<BasicService>(); 

    return kernel; 
} 

它將注入(在地方在需要IService),用於VIP用戶BasicService一些基本用戶和ExtraService

有關條件綁定的各種方式的更多信息,請參見Ninject - Contextual binding

編輯

我覺得你還是可以使用條件綁定。您只需要將IKernel傳播到您想要從新dll註冊組件的位置。例如,我在我的global.asax中爲動態加載dll模塊提供了這個功能 - 它在應用程序啓動時運行。

加載模塊:

private void LoadAssemblies(IKernel kernel) { 
    foreach (var fileName in Directory.GetFiles(Server.MapPath("~/App_Data"), "*.dll")) { 
     Assembly loadedAssembly = Assembly.LoadFile(fileName); 
     try { 
      var moduleRegistrations = loadedAssembly.GetTypes() 
       .Where(t => t.IsClass && t.IsAbstract == false && typeof (IMyModuleRegistration).IsAssignableFrom(t)); 

      foreach (var moduleRegType in moduleRegistrations) { 
       IMyModuleRegistration moduleReg = (IMyModuleRegistration) Activator.CreateInstance(moduleRegType); 
       moduleReg.RegisterComponents(kernel); 
      } 
     } 
     catch (ReflectionTypeLoadException exception) { 
      .... 
     } 
    } 
} 

模塊定義:

public class MyExtraModule : IMyModuleRegistration 
{ 
    public void RegisterComponents(IKernel kernel) 
    { 
     kernel.Bind<IService>() 
       .To<ExtraService>() 
       .When(x => x.ParentContext 
          .Kernel.Get<IAuthorizationService>() 
          .IsVIPUser()); 
    } 
} 

ExtraService將與MyExtraModule DLL被加載時,纔可以使用。

EDIT 2

您可以從什麼地方下載DLL。加載它,然後測試它是否實現了您的註冊界面。然後致電該註冊並完成。我看到的唯一問題是:在哪裏存儲對IKernel的引用 - 可能在HttpApplication中的一些靜態屬性就足夠了。你還應該跟蹤已經加載的dll。

或在Ninject的更高版本中,我可以建議擴展NinjectModule,然後使用kernel.Load(..)方法將其加載到內核中。看看這Modules and kernel - 特別是在部分動態模塊加載 - 也許這是你在找什麼。

+0

我修改了這個問題以更好地解釋我自己。你可以再看一下嗎? – deanvmc

+0

更新了我的答案。希望能幫助到你。 – mipe34

+0

我已經給你一個upvote,因爲它更接近我所需要的。我看到的唯一問題是,我對dll一無所知,除非我在請求中找到並加載它的URL,因此我無法在啓動時執行此操作。我需要能夠在特定用戶的第一個請求下基本上延遲加載dll,並介意只有該用戶才能使用的服務。我在想這個慣例方法可以幫助解決這個問題。 – deanvmc

2

使用條件綁定:

Bind<IMyService>().To<MyService>(); 
Bind<IMyService>().To<MyServiceForVIPs>().When(ctx => CurrentPrincipalIsVIP()); 
+0

我修改了這個問題以更好地解釋我自己。你可以再看一下嗎? – deanvmc

1

我假設你知道核心ninject模塊。您可以將所有核心ninject模塊加載到內核中。當特殊用戶到達時,您可以卸載核心模塊並將用戶特定模塊加載到內核中。

一個更好的方法是在插件區域有一個特殊的內核。所以實際上每個插件的內核方法都會加載所需的核心模塊,並添加用戶特定的模塊(如果有的話)。但是這可能會對性能產生影響!

+0

是的,所有核心模塊都是在開始時加載的。子內核的想法很有趣,我注意到有一個子內核擴展集。 – deanvmc