13

I'm looking at building a WCF service that can store/retrieve a range of different types. Is the following example workable and also considered acceptable design:

[ServiceContract]
public interface IConnection
{        
   [OperationContract]
    IObject RetrieveObject(Guid ObjectID); 

   [OperationContract]
    Guid StoreObject(IObject NewObject); 


}

[ServiceContract]
[ServiceKnownType(IOne)]
[ServiceKnownType(ITwo)]
public interface IObject
{
    [DataMember]
    Guid ObjectID;

}

[ServiceContract]
public interface IOne:IObject
{
    [DataMember]
    String StringOne;

}

[ServiceContract]
public interface ITwo:IObject
{
    [DataMember]
    String StringTwo;

}

When using the service, I would need to be able to pass the child types into the StoreObject method and get them back as their Child type from the RetrieveObject method.

Are there better options?

Thanks, Rob

4

1 回答 1

18

您的示例将无法编译,因为接口不能包含字段,即 ObjectID、StringOne 和 StringTwo。您尝试使用 IObject、IOne 和 ITwo 定义的是数据合同,而不是服务合同。因此,您应该使用 DataContract 属性,而不是 ServiceContract 属性和类,而不是接口。

[DataContract]
[KnownType(typeof(MyOne))]
[KnownType(typeof(MyTwo))]
public class MyObject
{
    [DataMember]
    Guid ObjectID;
}
[DataContract]
public class MyOne : MyObject
{
    [DataMember]
    String StringOne;
}
[DataContract]
public class MyTwo : MyObject
{
    [DataMember]
    String StringTwo;
}

请注意,这些是类,而不是接口。DataContract 属性已替换 ServiceContract 属性。KnownType 属性已替换 ServiceKnownType 属性。从我所看到的来看,这更规范。

然后,您的服务合同将定义如下:

[ServiceContract]
public interface IConnection
{
    [OperationContract]
    [ServiceKnownType(typeof(MyOne))]
    [ServiceKnownType(typeof(MyTwo))]
    MyObject RetrieveObject(Guid ObjectID);

    [OperationContract]
    [ServiceKnownType(typeof(MyOne))]
    [ServiceKnownType(typeof(MyTwo))]
    Guid StoreObject(MyObject NewObject);
}

您可以将 ServiceKnownType 属性放在合同级别(即,在 ServiceContract 属性下),以使其适用于合同的所有操作。

[ServiceContract]
[ServiceKnownType(typeof(MyOne))]
[ServiceKnownType(typeof(MyTwo))]
public interface IConnection
{
    [OperationContract]
    MyObject RetrieveObject(Guid ObjectID);

    [OperationContract]
    Guid StoreObject(MyObject NewObject);
}

可以像这样在数据合约中使用接口:

interface IEmployee
{
    string FirstName
    { get; set; }
    string LastName
    { get; set; }
}
[DataContact]
class Employee : IEmployee
{...}

但是,导出的元数据中不包含 IEmployee 接口。因此,如果您使用 svcutil 生成代理类,您的客户将不会知道 IEmployee。如果您的服务和客户端驻留在同一个应用程序中,这没什么大不了的(这是在应用程序域之间进行通信的好方法)。但是,如果您的客户端与您的服务是分开的(在绝大多数情况下,它将是),这将成为问题,因为您必须手动复制客户端上的 IEmployee 接口。

于 2009-03-25T14:22:23.903 回答