我们正在通过WCF提供服务。我们使用Entity Framework,Automapper和DTO公开了SQL Server中的数据。
我们很乐意在DTO中提供属性,但不确定如何实现我们希望在类库中保存的其他方法。
我们只想引用在类库中实现的方法,而不是将整个服务的所有方法都放在单个WCF服务实现中。
我们如何通过类库实现业务逻辑层,通过WCF暴露给表示层并使用DTO传递数据?
暴露的类方法是如何引用DTO的?类库是否应按层分割?
服务元素
[的ServiceContract]
public interface Interface1
{
[OperationContract]
Class1 GetClass1(int id);
[OperationContract]
Class2 GetClass2(int id);
}
类库元素
public class Class1 : Interface1
{
public Class1 GetClass1(int id) {
// implementation
}
}
public class Class2 : Interface1
{
public Class2 GetClass2(int id)
{
// implementation
}
}
DTO的
[DataContract]
public class Class1
{
[DataMember]
public int x { get; set;}
}
[DataContract]
public class Class2
{
[DataMember]
public int y { get; set;}
}
答案 0 :(得分:1)
如果我理解你的问题。你不想要所有以自动方式曝光的方法。如果你只想抽象几种方法,那么你就可以在服务和类服务中共享共同的DTO。
答案 1 :(得分:1)
是的,您可以将类库用于WCF服务(WCF下的Visual Studio中的项目用于WCF类库)。这个类库将保存服务契约的实现 - 服务契约也可以在类库中定义,或者可以在类库引用的另一个程序集中。
然后需要托管此类库(IIS,自托管或Windows服务)。我们在工作中这样做 - 我们有一个n层应用程序,它使用WCF在层之间进行通信,所有服务本身都在类库中实现并托管(通常在IIS中,在一个案例中在Windows服务中)
采用已发布代码的修改版本(实现类和DTO时应该有不同的名称),您可以执行以下操作:
班级图书馆
[ServiceContract]
public interface Interface1
{
[OperationContract]
Class1 GetClass1(int id);
[OperationContract]
Class2 GetClass2(int id);
}
public class Service1 : Interface1
{
public Class1 GetClass1(int id)
{
// implementation
}
public Class2 GetClass2(int id)
{
// implementation
}
}
请注意,一个服务类,它实现了服务定义(Interface1
)中定义的两个操作合同。你发布的代码不会编译,因为这两个类都没有实现接口中定义的两个方法(你也会因为它们的返回类型而至少得到类名的警告)。
然后,您可以将此类库的引用添加到您拥有DTO(Class1
和Class2
)的程序集中。
要在自托管方案或Windows服务中托管它,您需要引用类库(在我的示例中为Service1
)以及对DTO程序集的引用。然后,您将实例化服务的服务主机,如下所示:
baseAddress = new Uri("some address");
ServiceHost myHost = new ServiceHost(typeof(Service1), baseAddress);
myHost.Open();
要在IIS中托管,您需要修改.svc文件标记,如下所示:
<%@ ServiceHost Language="C#"
Service="MyCompany.Service1"
Factory="System.ServiceModel.Activation.ServiceHostFactory" %>
您需要使用完整命名空间完全限定服务名称,因此假设Service1
的命名空间为MyCompany
,则完全限定名称为MyCompany.Service1
。
最后,您需要将相关的system.serviceModel
部分放在相应的托管应用程序的app.config或web.config文件中,因为库使用其使用应用程序的配置文件,不是他们自己的。
这个主题有很多微妙的变化(在我们的例子中,我们使用自定义服务主机和自定义服务主机工厂,接口 - 服务契约 - 在一个单独的程序集中,这允许我们通过{创建代理{1}}。
要回答您的最后一个问题,如果他们打算使用它们,那么类库(ies)将必须引用包含您的DTO的程序集,并且您可以拆分您认为符合您要求的服务类库 - 我如果你有多个应用程序,它肯定会至少按层分割,也可能通过垂直堆栈分割它们。
答案 2 :(得分:1)
首先让我澄清一下(我认为)你要做的事情:
您希望通过WCF公开一些业务逻辑,最终将由您的表示层使用。业务逻辑涉及访问数据库并使用ORM和AutoMapper。就您的问题而言,我认为此实施的细节无关紧要。
让我们对看起来像的东西进行第一次迭代(我会将不同的名称空间分离到不同的程序集中):
namespace Contracts
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
Data GetData(int id);
}
[DataContract]
public class Data
{
[DataMember]
public string PropertyValue { get; set; }
}
}
namespace ClassLibrary
{
public class BusinessLogicImplementation: IMyService
{
public Data GetData(int id)
{
/**
* Do data retrieval here, which returns returnedData
* */
DataModel returnedData;
return Mapper.Map<DataModel, Data>(returnedData);
}
}
}
namespace EntityFrameworkModel
{
public class DataModel
{
public string PropertyValue { get; set; }
}
}
“合同”程序集包含对服务和客户端都公开的数据。客户端可以通过对程序集的二进制引用,也可以由具有自己的本地合同实现的客户端(如Visual Studio服务引用)来使用它。
类库程序集包含数据检索和业务逻辑的实现。我还展示了数据模型 - 但仅限于额外的上下文 - 我不认为这与您的问题相关:
到目前为止,我们已经回答了部分问题:
“我们如何通过类库实现业务逻辑层,通过WCF暴露到表示层并使用DTO传递数据?”
接下来让我们考虑一下您的查询的第一部分:
“我们只想引用在类库中实现的方法,而不是将整个服务的所有方法都放在单个WCF服务实现中。”
虽然您没有明确建议,但这表明您的WCF服务暴露的方法多于与您的客户相关的方法。非常正确地说,您希望使客户看到的界面简洁,与他们想要实现的目标相关。
这是通过在由不同接口表示的服务上公开不同的端点来实现的。在代码方面,我在业务逻辑的实现和通过WCF公开的实现之间添加了一个额外的层:
namespace Contracts
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
Data GetData(int id);
}
[DataContract]
public class Data
{
[DataMember]
public string PropertyValue { get; set; }
}
}
namespace MoreContracts
{
[ServiceContract]
public interface IOtherService
{
[OperationContract]
MoreData GetMoreData(int id);
}
[DataContract]
public class MoreData
{
[DataMember]
public string MorePropertyValue { get; set; }
}
}
namespace Service
{
/**
* This class adds an extra layer between the exposed functionality and the implementation.
* It effectively is used for hosting all the business logic you want to expose over the service,
* including that contained in ClassLibrary and anywhere else.
* */
public class ServiceImplementation: IMyService, IOtherService
{
public Data GetData(int id)
{
return new BusinessLogicImplementation().GetData(id);
}
public MoreData GetMoreData(int id)
{
//Implementation of logic not in class library
}
}
}
namespace ClassLibrary
{
public class BusinessLogicImplementation : IMyService
{
public Data GetData(int id)
{
/**
* Do data retrieval here, which returns returnedData
* */
DataModel returnedData;
return Mapper.Map<DataModel, Data>(returnedData);
}
}
}
在线快速搜索将向您展示如何为托管方案托管具有多个endoints的服务。例如。自我托管请参阅Run WCF ServiceHost with multiple contracts。