时间:2010-07-26 17:22:02

标签: c# wcf generics serialization serviceknowntype

4 个答案:

答案 0 :(得分:12)

如果您真的想要,可以在服务合约定义中使用接口,只要您按照自己的方式包含已知类型(稍作调整,请参见下文)。

显然,使用接口作为泛型类型参数使其成为C#3.0的桥梁。我将已知的类型属性更改为

[ServiceKnownType(typeof(Batch<Command>))]
public interface IActions
{
}

这使得它在某种程度上起作用。序列化和反序列化本身也可以,但是你遇到了这个例外:

  

无法转换'Batch`1 [Command]'类型的对象   输入'IBatch`1 [ICommand]'。

要使该转换工作,您需要语言支持泛型类型协方差,这是C#4.0中引入的。但是要在C#4.0中工作,你需要添加一个方差修饰符:

public interface IBatch<out T>
{
}

然后它完美地工作......不幸的是你没有使用C#4.0。

在服务合同中使用接口的最后一件事:如果您从它们生成服务引用,它将所有接口参数键入为object,因为原始接口类型不是元数据。您可以通过程序集引用共享契约,或手动重构生成的代理来修复它,但总而言之,使用WCF的接口可能比它的价值更麻烦。

答案 1 :(得分:2)

答案 2 :(得分:1)

答案 3 :(得分:1)

泛型可以序列化,但有一定的局限性。例如,给定数据合同:

[DataContract]
public class Foo<T>
{
     [DataMember]
     public T Value { get; set; }
}

服务合同:

[ServiceContract]
public interface IService1
{
     [OperationContract]
     Foo<String> GetData();
}

服务实施:

public class Service1 : IService1
{
   public Foo<string> GetData()
   {
       return new Foo<string>() { Value = "My test string" };
   }
}

在为上述服务设置服务参考后,可以运行以下代码:

ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();

ServiceReference1.FooOfstring temp = client.GetData();

MessageBox.Show(temp.Value);

显示带有“我的测试字符串”的消息框。

请注意,服务本身不是通用的,但使用的数据合同是。此外,在客户端生成的数据协定不是通用的,而是具有类型为string的属性值的“扁平”类:

[System.Runtime.Serialization.DataMemberAttribute()]
public string Value 
{ 
   get {...} 
   set {...} 
}