前言:
这是迄今为止我在这里留下的最长的帖子......但我认为在这种情况下这是必需的。
很长一段时间以来,我一直对这类事情有疑问:如何命名程序集,以及如何在其中划分类。
我想在这里给出一个应用程序的示例,仅用最少的类来演示我想要理解的内容。
想象一个应用程序
- 接受客户端消息,将它们存储在数据库中,然后将它们出列到 MTA 服务器。
- 它是一个 Web 应用程序,具有用于编写消息和附加附件的 ASP.NET 接口。
- 还有一个 Silverlight 客户端,因此 Web 应用程序公开一个 ClientServices WCF ServiceContract,以及一个 OperationContract (SaveMessage)。
- 还有一个 Windows 客户端...与 Silerlight 合约执行相同的操作。
好的。这应该足以证明我的无知是一个假场景。
上面将需要以下类:
-
Message
-
留言地址
-
MessageAddressType(带有 From、To 的枚举)
-
消息地址集合
-
留言附件
-
消息附件类型
-
留言附件集合
-
消息异常
-
消息地址格式异常
-
MessageExtensions(消息的静态扩展)
-
MessageAddressExtensions(MessageAddress 的静态扩展)
-
MessageAttachmentExtensions(MessageAttachment 的静态扩展)
项目.合同.dll
我将上述内容组织到正确的程序集中的第一个尝试是观察 Message、MessageAddress、MessageAttachment、其属性所需的枚举(MessageAddressType、MessageAttachmentType)以及它们所需的集合(MessageAddressCollection、MessageAttachmentCollection)都将标记为[DataContract] 使它们可以在WCF客户端和服务器之间序列化。
由于两者都是共同的,我想我会将它们移动到一个名为 Contract 的中立共享程序集中。
项目.Client.dll
我需要服务器 [ServiceContract] 的客户端代理,它引用 Contract.dll 中的类。
因此,现在服务器(也引用 Project.Contract.dll)现在可以保存从 WCF 客户端接收到的序列化消息,并将它们保存到数据库中。
Plugins
接下来我会意识到我希望由第 3 方插件(例如病毒检查器)在服务器端处理这些对象...
但是插件应该对变量具有只读访问权限(仅),以便检查变量,并在看到不喜欢的内容时抛出错误。
所以我会考虑回去让 Message 继承自 IMessage Read Only ...但是该接口放在哪里呢?
项目接口.dll
如果我将它放在一个名为 Project.Interfaces.dll 的程序集中,这将适用于可以引用该程序集而无需引用 Contracts.dll 的插件...但现在客户端必须同时引用 Contracts 程序集和接口...听起来不是一个好方向...
重复对象
或者,我可以有两个 Messages 结构(并复制其他 MessageAttachment 等类)...一个用于从客户端到服务器的通信(在 Contracts.dll 中),然后使用第二个 ServerMessage/ServerMessageAddress/ServerMessageAddressCollection服务器端,继承自IMessageReadOnly,然后看起来我更接近我想要的了。
对于重复的对象,插件的访问受到限制,而服务器 BL 等对其工作相关的类型具有完全访问权限,而客户端具有不同但相同的对象......
事实上......我可能应该开始将它们视为不相同,让我的头脑更清楚这些对象只是在那里与客户交谈,即合同/通信对象)...
网站用户界面
这会产生...嗯...如果有两个不同的消息,并且它们现在具有不同的属性...哪一个最适合用于支持 ASP.NET 表单? ServerMessage 对象似乎最快(类型之间没有映射)...但是所有逻辑都已经针对客户端消息对象(具有不同的属性和内部逻辑)制定出来。那么我是否会使用 ClientMessage 并将其映射到 Servermessage,以在不同的媒介上保持各种 UI 逻辑相同?或者我应该更喜欢映射,并重写 UI 验证?
第三种情况呢,Silverlight...合同程序集是一个完整的框架程序集...Silverlight 无法引用(不同的框架/构建机制)...所以我在 Silverlight 端的程序集可能是完全相同的代码,但必须是不同的程序集。结果怎么样?
到底要考虑什么作为数据契约?
最后...我发誓,这就是我的大问题即将结束的地方...那些不明确是 DataContract 的讨厌的额外类怎么办?
例如,MessageAddress 是一个 DataContract。好的。它公开的枚举是其中的一部分...有意义...但是如果 messageAddress 构造函数引发 MessageAddressFormatException...它是否被视为 DataContract 的一部分?
服务器、客户端和插件是否可以有共同的类?
或者它是 ServerMessageAddress 和 ClientMessageAddress 共同的异常,因此不应重复,而应该在 Common 程序集中......这样最终客户端必须绑定到 Contracts 和 Common? (我们不是刚刚和接口组件一起沿着这条小巷走下去的吗?)
常见的基类/接口怎么样?
这些异常应该有共同的基类吗?例如...ClientMessageAddressException、ServerMessageAddressException、ServerMessageVirusException(来自插件)...我是否应该努力让它们尽可能地全部源自抽象 MessageException...或者是否存在继承/重用的时候只是不再是一个合适的奋斗目标?
非常感谢您阅读本文。
我是一名开发人员,在技术方面我可以笨手笨脚地走下去……但是这些类型的问题,我必须自己布置组件、架构,让我非常困惑……并且迷失了我花了很多时间,我把自己逼疯了,将东西从一个组件移动到另一个组件,看看哪一个最适合,同时不确定我在做什么,并试图不得到循环引用......
所以,真的,感谢您的聆听,我希望能够描述如何清晰地阐述上述内容的人能够阅读本文,并希望能够表达出我对未来项目的思考方式。