2012-12-28 88 views
1

我使用Autoface創建了一個新的MVC4網站,該網站具有公共消費者網站以及用於管理面向消費者的網站的管理區域。管理網站將位於不同的區域使用與面向消費者的網站相同的服務,但不具有某些自定義品牌特徵。Autofac每個區域的依賴關係

我遵循了其他地方給出的有關ViewDataFactory的建議,該ViewDataFactory爲視圖提供了一組共享數據。我的目標是取決於你在什麼區,以提供不同的ViewDataFactory。

因此,舉例來說,這裏是一個實現IViewDataFactory

builder.RegisterType<SelfServiceViewDataFactory>().As<IViewDataFactory>(); 

這給了我一個的ViewFactory將其注入到我的所有控制器的服務。但是我想要到acheive是這樣的(沒有功能代碼):

builder.RegisterType<ViewDataFactory>().As<IViewDataFactory>().ForType(ControllerBase1);  
builder.RegisterType<DifferentViewDataFactory>().As<IViewDataFactory>().ForType(ControllerBase2);  

在控制器類型或MVC面積將確定哪些服務得到解決。

編輯

爲了澄清我的帖子有兩個問題:

  1. 是否有Autofac的方式說「只爲X型的類,Y型的服務將提供實例Z「?
  2. 有沒有辦法改變Autofac行爲的基礎上使用該組件的區域?

從我一直在閱讀的所有內容來看,#1的答案似乎是「否」,除非您有一個參數用於檢查要提供哪個組件。我知道Ninject可以提供基於命名空間的依賴關係,所以其他框架似乎可以處理這種情況。似乎解決方案是提供參數或定義兩種不同的服務。

我還沒有真正看過Autofac和MVC領域的很多討論,所以我猜#2也不可能沒有自定義解決方案。謝謝!

+0

Essentiall y,你將有一個模塊化設計,每個區域有一個單獨的容器參考,對嗎? –

+0

是的。有沒有辦法爲每個區域設置一個Autofac容器? – AlexT

+0

如果他們正在做重大不同的事情,你真的想將這兩個具體類填入'IViewDataFactory'?怎麼樣'ControllerBase1'依賴ViewDataFactory,同樣'ControllerBase2'依賴'DifferentViewDataFactory' – wal

回答

2

使用命名服務可能是您的最佳選擇。所以你會這樣做:

builder 
    .RegisterType<ViewDataFactory>() 
    .Named<IViewDataFactory>("Area1");  

builder 
    .RegisterType<DifferentViewDataFactory>() 
    .As<IViewDataFactory>("Area2"); 

然後,如果你想避免不得不手動註冊你的控制器。您可以使用此代碼,我只是拼湊起來的,並沒有測試:

把這個屬性的地方全局可訪問:

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 
public class ServiceNamedAttribute : Attribute 
{ 
    private readonly string _key; 

    public ServiceNamedAttribute(string key) 
    { 
     _key = key; 
    } 

    public string Key { get { return _key; } } 
} 

加入這個模塊你Autofac配置:

public class ServiceNamedModule : Module 
{ 
    protected override void AttachToComponentRegistration(
     IComponentRegistry registry, IComponentRegistration registration) 
    { 
     registration.Preparing += 
      (sender, args) => 
      { 
       if (!(args.Component.Activator is ReflectionActivator)) 
        return; 

       var namedParameter = new ResolvedParameter(
        (p, c) => GetCustomAttribute<ServiceNamedAttribute>(p) != null, 
        (p, c) => c.ResolveNamed(GetCustomAttribute<ServiceNamedAttribute>(p).Name, p.ParameterType)); 

       args.Parameters = args.Parameters.Union(new[] { namedParameter }); 
      }; 
    } 

    private static T GetCustomAttribute<T>(ParameterInfo parameter) where T : Attribute 
    { 
     return parameter.GetCustomAttributes(typeof(T), false).Cast<T>().SingleOrDefault(); 
    } 
} 

而且那麼你仍然可以自動註冊你的控制器裝飾構造如下:

public class Controller1 
{ 
    public Controller1(ServiceNamed["Area1"] IViewDataFactory factory) 
    { ... } 
} 
+0

謝謝,我將不得不關注一下命名服務。我不確定如何在沒有明確詢問容器中使用該名稱的服務的情況下如何使用它們。名稱屬性類是一個有趣的方式來做到這一點。 – AlexT

+0

如果您不想添加該屬性,而寧願使用該類的名稱空間,則應該可以在「準備」事件處理程序中執行此操作。只需找到'args'的適當屬性即可。 –