2011-11-04 49 views
6

我正在使用註冊表DSL示例來配置結構圖。但是這樣做可以使我的應用程序的所有層都可以使用我所有的註冊類型,我可以在其中添加參考結構圖。我不希望我的業務層瞭解我的數據訪問層,反之亦然。我如何獲得結構圖只爲每個圖層註冊特定類型?結構圖 - 如何在特定層中註冊某些類型

這裏是我的Global.asax文件中的代碼:

ObjectFactory.Initialize(x => 
{ 
    x.AddRegistry<RegistryIOC>(); 
}); 

這裏是我的RegistryIOC類:

public class RegistryIOC : SMRegistry 
{ 

    public RegistryIOC() 
    { 
     For<IProfileService>.Use<ProfileService>(); 
     For<IProctorService>().Use<ProctorService>(); 

     //Business Logic Objects 
     For<IQual>().Use<Qual>(); 
     For<ITest>().Use<Test>(); 
     For<IBoldface>().Use<Boldface>(); 
     For<ITrainingPlan>().Use<TrainingPlan>(); 
     For<IUnit>().Use<Unit>(); 

     //Data Transfer Objects 
     For<IGenericDTO>().Use<GenericDTO>(); 
     For<IProfileDTO>().Use<ProfileDTO>(); 
     For<IQualDTO>().Use<QualDTO>(); 
     For<IPermissionDTO>().Use<PermissionDTO>(); 

     //Repository Objects 
     For<IProctorRepository>().Use<ProctorRepository>(); 
     For<IQualsRepository>().Use<QualsRepository>(); 
     For<ITestRepository>().Use<TestRepository>(); 
     For<IUnitRepository>().Use<UnitRepository>(); 
     For<IUserRepository>().Use<UserRepository>(); 
    } 

} 

感謝您的幫助。

+0

你在說什麼樣的圖層?不同的流程?不同的機器?如果他們都在同一個進程中運行,那麼你可能會做你的業務層知道你的數據層,特別是它的接口。目前還不清楚你想要解決什麼問題。你的RegistryIOC類有什麼問題? –

+0

我們有一個服務層,BLL和DAL,這些都是單獨的項目。每個項目都引用StructureMap。 服務層知道其他兩層,但BLL和DAL不知道對方。 我不希望其他開發人員利用DAL內的Business Objects,反之亦然我不希望開發人員利用BLL內的Repository對象。服務層對所有這些問題進行管理。 因此,使用這種方式註冊所有類型,所有對象都可以跨所有圖層(項目)使用。 –

+0

好吧,*不要*從組合根目錄以外的任何其他層添加對StructureMap的引用... –

回答

3

我正在使用反射來完成此(和其他)任務。讓我展示這是如何工作的。

做的第一件事是定義一個接口,使我們能夠識別執行初始化任務等級:

public interface IConfigurationTask 
{ 
    void Configure(); 
} 

接下來,創建實現此接口的一個或多個類別。這些課程將分散在你的所有項目中,這是另一種說法,你可以把它們放在「他們所屬的地方」。

public class RepositoryInitializer : IConfigurationTask 
{ 
    public void Configure() 
    { 
     // code that does relevant initialization goes here 
    } 
} 

最後一塊難題是找到實現IConfigurationTask接口的類,創建它們的一個實例並執行Configure方法。這是ConfigurationTaskRunner的目的:

public static class ConfigurationTaskRunner 
{ 
    public static void Execute(params string[] assemblyNames) 
    { 
     var assemblies = assemblyNames.Select(Assembly.Load).Distinct().ToList(); 
     Execute(assemblies); 
    } 

    public static void Execute(IEnumerable<Assembly> assemblies) 
    { 
     var tasks = new List<IConfigurationTask>(); 
     assemblies.ForEach(a => tasks.AddRange(a.CreateInstances<IConfigurationTask>())); 

     tasks.ForEach(t => t.Configure()); 
    } 
} 

這裏顯示的代碼使用一個自定義擴展到所有項目遍歷一個列表,併爲每個項目(給ForEach方法)執行相應的操作。我還使用reflection library來完成查找和實例化單線程(CreateInstances方法)的任務,但您可以使用簡單的反射(如下面的代碼所示)實現相同的任務。

public static IList<T> CreateInstances<T>(this Assembly assembly) 
{ 
    var query = from type in assembly.GetTypes().Where(t => typeof(T).IsAssignableFrom(t) && typeof(T) != t) 
       where type.IsClass && ! type.IsAbstract && type.GetConstructor(Type.EmptyTypes) != null 
       select (T) Activator.CreateInstance(type); 
    return query.ToList(); 
}  

拼圖的最後一部分是觸發ConfigurationTaskRunner的執行。例如,在一個Web應用程序,這將進入的Application_Start在Global.asax中:

// pass in the names of the assemblies we want to scan, hardcoded here as an example 
ConfigurationTaskRunner.Execute("Foo.dll", "Foo.Domain.dll"); 

我還發現它有用與派生IPrioritizedConfigurationTask(即增加了一個優先級屬性),允許的任務的正常排序前你執行它們。這在上面的示例代碼中沒有顯示,但添加相當微不足道。

希望這會有所幫助!

+0

在這個例子中(這很棒)你如何提出鏈接依賴關係?如果我想要一個支持ProdCeporo的ProdCacheRepo支持的IProdRepo實例......你會怎麼做鏈接?好奇! –

+0

@AndrewSiemer我認爲這將是IoC框架(在這種情況下是StructureMap)的任務,基於您提供給它的配置(在各個配置方法中)。我提供的代碼僅僅是IoC容器的「分佈式配置」機制(或任何你需要在應用程序啓動時初始化的)。 –

+0

我無法使用反射庫。當我通過正則反射嘗試此代碼時,a.CreateInstance(「IConfigurationTask」),我沒有得到任何結果。也許我錯過了什麼地方... :-( –

0

您可以創建和配置多個獨立的Container實例,並且根本不使用靜態ObjectFactory - see this article。那麼你有責任爲適當的層提供適當的容器。

順便說一句,你想如何處理層間通信?難道不會有些困難嗎?我寧願拆分註冊表(可能要分離程序集),並將其「手動」解耦,而不是在基礎結構級別強制解耦。

+0

我不介意改變我當前的實現。如果最好讓我的每個圖層上的所有註冊表都分開上課,那就很酷。我的問題的一部分是我不完全理解如何「提供適當的容器適當的層」。我究竟把什麼放在global.asax加載器中? –

+0

那麼,一般來說,對於不同的圖層,每個圖層都必須有不同的入口點,並且每個圖層都需要使用適當的容器擁有自己的工廠方法 - 這樣,每個圖層都會有單獨的對象圖。但我真的不知道如何完成這些圖表之間的任何交互,所以這就是第二段中的問題的原因。最後,你必須有一些使用下層組件Y的上層組件X.如果X是中間層並且由中間層容器創建,那麼它的依賴Y也是如此,即使它是來自底層。 – NOtherDev

+0

所以一般來說,答案是很難完全解耦對象圖。這就是爲什麼我建議在註冊表/程序集級別而不是對象工廠級別解耦。 – NOtherDev

相關問題