2011-11-04 45 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

相关问题