2009-08-24 54 views
4

我有一对夫妇与循环引用/依赖,我已经坐在了一整天的问题。我的思考过程中一定是错的,我只是不明白。解决循环引用(C#)

这里是我的项目:

Flip.Main  (ASP.NET MVC) 
Flip.Domain (C# DLL) 
Flip.Services (C# DLL) 
Flip.Utility (C# DLL) 

基准电流/依赖性:

Flip.Main ->  Flip.Domain, Flip.Services, Flip.Utility 
Flip.Services -> Flip.Domain, Flip.Utility 
Flip.Domain -> Flip.Utility 

我要组织我的项目,我的服务项目有所有服务的方式,我的领域的项目模型,资料库和'流利'扩展来查询模型,主要和实用工程几乎是自我解释。遇到

问题:

1)我有我的Flip.Services项目,该项目需要派出本地化电子邮件的EmailService。所有本地化都在Flip.Main的App_GlobalResources中完成。不知道如何将强类型电子邮件和其他本地化资源现在加入到我的服务层,因为Flip.Main已经取决于服务层,因此我可以依赖于主项目。

2)我有业务类,例如CustomerSearchFilter表示一个强类型的搜索查询。我希望Flip.Domain项目之外的业务类,因为它们不属于域模型的一部分。然而,在我的CustomerSearchFilter类中,我有域类实例(例如CustomerGroup),因此它需要知道域类。同时,我的Flip.Domain项目中的Fluent界面需要知道CustomerSearchFilter是什么,所以我可以将它应用到我的IQueryable接口。再循环参考。

3)我有一个自定义[AuthorizeSessionState]属性,我用我的ASP.NET MVC Flip.Main项目来装饰特定的控制器动作。这是一个ActionFilterAttribute,它需要实例化驻留在我的Flip.Services项目中的SessionService。我不能把它放到我的Utility类中(因为Flip.Services已经引用了Flip.Utility)。我不认为他们应该在Flip.Main - 我必须为此做另一个项目!?

(20以上)

我觉得我犯了一个错误的地方的路线,尤其是当我看到别人通常不会遇到循环引用的问题。帮帮我?

回答

5

使用所有非平凡类的接口。将接口放置在与实现不同的组件中。

+2

这就是我要为第2项提出的建议。如果您觉得两个兄弟组件需要知道对方的类,只需分开一个接口并让它们都使用它们即可。 – 2009-08-24 06:36:59

+0

您可以考虑的一件事是使用基本类型与虚拟成员而不是接口。通过这种方式,您可以为主机应用程序提供功能性的默认实现,这可以使测试变得更简单,并与实现共享一些逻辑。 – mcintyre321 2013-06-27 10:41:26

0

问题归结到你的命名空间,您可以通过DLL分开单独什么什么。如果你有一个很好的理由来保持一切的模块化,你必须努力工作。但是,如果这些DLL中的每一个都只有一个或两个类,那么也许你可以将它们合并在一起?

+0

该DLL相当大。我在Flip.Services DLL中有12种不同的服务(可能会增长到> 20)我的Flip.Domain DLL中的模型,模型部分类扩展,存储库类和流畅的扩展方法,Flip.Utility中的加密和业务支持类以及Flip.Main中的网站。对我来说似乎合乎逻辑? – Alex 2009-08-24 05:13:33

+0

那么命名空间是。如果您希望在不使用整个程序的情况下更新它们,并重新使用代码,则可以使用程序集。但正如我所说,如果你只有一个应用程序或一小组共享功能,那么把所有东西放在一起。 – Spence 2009-08-25 00:34:49

0

花几分钟的时间,整理程序...为每个项目创建一个标识符(FM,FS,FD,FU)。页面上列出的每个公开访问的过程,然后添加一个标识为一个项目,如果该项目使用的过程...

然后你就可以看到哪些程序需要在(或访问)的项目。

希望有帮助!

+0

正如我在上面写的那样,问题在于2个项目经常需要互相了解。你的方法如何解决它? – Alex 2009-08-24 05:30:23

+0

如果你尝试这个建议,你会看到(除其他外,我敢肯定)你的一些过程并不是最适合的项目......例如在main和not util中进行本地化似乎并不正确。根据您之后的模块化级别,您可能会发现语言管理完全适合自己。 – 2009-08-24 06:21:16

0
  1. 您可以将您的本地化电子邮件字符串置于Flip.Services中。缺点是你有两个地方来维护本地化资源。你也可以为你的所有资源设置一个单独的dll来最小化编辑资源的地方。
  2. 您必须将流畅接口移动到其他dll或使CustomerSearchFilter成为域的一部分。
  3. 您将需要添加更多项目或重新排列结构并使用命名空间来创建分隔。
+0

将使得CustomerSearchFilter(和其他没有数据表示的业务对象)成为该域的一部分吗? – Alex 2009-08-24 05:48:38

0

这听起来像你的具体实现而不是接口/合同的建设。正如Ima建议定义界面来描述某个类应该能够做什么。当你声明属性,参数等时使用这个接口。保持接口与实现分离,实现和使用接口的项目都可以引用接口项目。

然后,您可以得到使用依赖注入使代码更容易测试作为一个侧

+0

你有这样的项目结构的例子文章或类似吗?这是常见的吗? – Alex 2009-08-24 05:47:37

0

在域的“层次”的不错的选择,存储库和服务住在同一个逻辑层次,域上方在基础设施角色。我建议将你的资源库实现(查询等)移到域本身之外。至少解决了#2。

+0

那会是什么样的项目? (技术术语?) – Alex 2009-08-24 06:34:41