我有一个解决方案结构,其中契约(数据/服务等)与业务实体位于不同的项目中,我使用Automapper在第三个服务实现项目之间进行映射.
WCFProject.Service.BusinessLayer
WCFProject.Service.Contracts
WCFProject.Service.Impl
我的ServiceImpl引用了这两个其他项目,从DataContract到BusinessEntity的自动化在这里完成,然后在BusinessEntity对象上调用正确的方法
现在,我想添加一些FaultContracts,然后在我的业务逻辑中使用它们来抛出正确的异常.但是,如果我将它们添加到Contracts项目(这是理想的,因为我想将所有合同保持在一起),那么我需要BusinessLayer引用合同以在BusinessLayer中使用它们.如果可能的话,我想保持这些独立性,并且只处理这两层之间的DTO.这是我的一个有效的方法,我想让这两个项目保持独立吗?你也映射了例外吗?或者有更好的方法来解决这个问题.
解决方法:
在您指定的问题中:
I want to add a few FaultContracts and then use them in my business logic to throw the right exceptions.
正如您所确定的那样 – 这引入了服务的公共API(服务,数据和错误契约)与业务逻辑之间的耦合.理想情况下,您的业务逻辑应该与服务调用它的事实无关,因此对合同程序集的引用令人不安.
合同大会应该列出客户对您的服务的公开信息:
namespace Contracts
{
[ServiceContract]
interface IMyService
{
[OperationContract]
[FaultContract(typeof(MyFaultContract))]
[FaultContract(typeof(AnotherFaultContract))]
void MyOperation();
}
[DataContract]
public class MyFaultContract
{
[DataMember]
public string Problem { get; set; }
}
[DataContract]
public class AnotherFaultContract
{
[DataMember]
public string Description { get; set; }
}
}
与软件开发中的许多问题一样,您的问题可以通过一层间接来解决.尽管您在问题中指定了 – 您不希望将业务逻辑耦合到合同程序集.不这样做的好处是显而易见的 – 它允许公共合同和“内部”业务逻辑独立发展.
下面显示了一个示例,其中服务实现用于将合同耦合到业务逻辑.业务层中的例外映射到故障合同,后者将返回给客户端:
namespace Service
{
class MyService: IMyService
{
public void MyOperation()
{
try
{
var businessLogic = new BusinessLogic();
businessLogic.DoOperation();
}
catch (KeyNotFoundException)
{
throw new FaultException<MyFaultContract>(new MyFaultContract
{
Problem = "A key issue occurred in the service"
});
}
catch (Exception)
{
throw new FaultException<AnotherFaultContract>(new AnotherFaultContract
{
Description = "Something BAD happened in the service"
});
}
}
}
}
顺便说一句,值得仔细考虑您在客户端公开的故障契约以及当服务器端出现问题时客户端需要哪些信息.在服务上公开过多的异常信息可能会带来安全风险.