WCF和类库

时间:2013-09-20 14:12:00

标签: .net wcf entity-framework dto

我们正在通过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;}
}

3 个答案:

答案 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(Class1Class2)的程序集中。

要在自托管方案或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