WCF 和接口 [英] WCF and interfaces

查看:25
本文介绍了WCF 和接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要有 2 个类家族(一个在服务器端,一个在客户端),它们的数据结构相同但行为不同.另外我认为这些 fmailies 会足够大,因此我不想实现 DTO 的中间级别以及与它的转换.我决定采取以下方式:声明共享程序集,并声明如下数据和服务接口:

I need to have 2 families of classes (one on server and one on client side) which are identical in data structure but differs in behavior. Also I suppose that these fmailies will be enough big, thus I don't want to implement intermediate level of DTO and transformations into and from it. I decided to move in following manner: declare shared assembly with declaration of data and services interfaces like these ones:

public interface ITest
{
    string Title { get; set; }
    int Value { get; set; }
}
public interface IService
{
    ITest GetData();
}

有了这些声明,我就可以在服务器端实现这些接口,例如基于实体框架(数据)和 WCF(服务).在客户端,我可以使用例如依赖属性(数据)和 WCF(服务).当我开始尝试实现这一点时,我遇到了几个麻烦.第一个是关于 WCF 的服务器端 - 它只是不想使用接口作为返回参数.感谢 StackOverflow,这个问题像这里一样得到解决.
下一个问题是服务器端呈现的 XML 包括在服务器类上序列化的合格程序集名称.

Having these declarations I can implement these interfaces on server side for example basing on Entity Framework (data) and WCF (services). On the client side I can use for example Dependency Properties (data) and WCF (service). When I started trying to implement this, I met several troubes. First one was about server side of WCF - it simply do not want to work with interfaces as return parameters. Thanks to StackOverflow this issue was resolved like here .
Next problem is that XML rendered by server side includes qulified assembly name of serialized on the server class.

      <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">  
        <s:Body>
          <GetDataResponse xmlns="http://tempuri.org/">
            <Test z:Id="1" z:Type="Dist.Server.Model.Test" z:Assembly="Dist.Server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns="http://schemas.datacontract.org/2004/07/Dist.Server.Model" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
              <Title z:Id="2">Test</Title>
              <Value>123</Value>
            </Test>
          </GetDataResponse>
        </s:Body>
      </s:Envelope>

因此在客户端反序列化期间尝试加载此类型.由于客户端无法访问此类型,因此我必须实现某种类型映射.我发现这很容易,因为用于序列化的 NetDataContractSerializer 支持 Binder 属性.因此,我在客户端覆盖此属性并返回正确的值(同时进行硬编码,但可以用于测试).

Thus during deserialization on client side there was an attempt to load this type. As this type is inaccessible on client side, I had to implement some kind of type mapping. I found that this is quite easy as NetDataContractSerializer used for serialization supports Binder property. Thus I override this property on client side and return correct value (hardcode in meantime, but it's OK for tests).

public class NetBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName) {
        var type = Type.GetType("Client.Test, Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
        return type;
    }
}

现在我有以下图片:
- 服务器使用 NetDataContractSerializer 来序列化响应.它在序列化期间使用实际值(calss)而不是在服务(接口)声明中使用的类型.
- 客户端接收 XML 并开始反序列化.为了解析类型,NetDataContractSerializer 调用返回正确类型的 Binder.
- NetDataContractSerializer 创建正确类型的实例并开始加载其属性.
在这里我遇到了一个我不知道如何解决的麻烦.属性值不会反序列化.这意味着正确创建了类的实例(通过反射服务创建的未初始化实例),但所有属性都处于默认值(0 或 null).我尝试在客户端使用类声明:将其标记为 [Serializable],实现 ISerializable 等,但没有任何帮助.NetDataContractSerializer 要求将类标记为 [DataContract] 或 [Serializable].第一个选项将属性留空,第二个选项导致异常,如</Test> 是意外,预期是 bla-bla-bla_Value_Ending_bla-bla-bla".

Now I have following picture:
- Server uses NetDataContractSerializer to serialize response. It uses actual value (calss) during serialization instead of type used in declaration of service (interface).
- Client side receives XML and starts deserialization. To resolve type, NetDataContractSerializer calls my Binder that returns correct type.
- NetDataContractSerializer creates instance of correct type and starts loading of its properties.
And here I got a trouble that I don't know how to resolve. Values of properties are not deserialized. It means that instance of class is created correctly (uninitialized instance created through reflection services), but all properties are in their default values (0 or null). I tried to play with declaration of class on client side: mark it as [Serializable], implement ISerializable, etc., but nohing is helpful. NetDataContractSerializer requires class to be marked as [DataContract] or [Serializable]. First option leaves properties empty, second one causes exceptions like "</Test> is unexpected, expected is bla-bla-bla_Value_Ending_bla-bla-bla".

有人对如何解决最后一步有任何建议吗?

Does anybody have any suggestions on how to resolve this last step?

我可以提供完整的资源以便更好地理解,但我不知道我是否可以将它们附在此处...

I can provide full sources for better understanding, but I don't know ifI can attach them here...

提前致谢.

推荐答案

看来问题已经很容易解决了.我创建了自己的序列化程序并使用它代替了 NetDataContractSerializer.代码很简单:

Seems that problem was solved enough easily. I created own serializer and used it instead of NetDataContractSerializer. Code is quite simple:

public class MySerializer: XmlObjectSerializer
{
    public override void WriteStartObject(XmlDictionaryWriter writer, object graph) {
    }

    public override void WriteObjectContent(XmlDictionaryWriter writer, object graph) {
        var formatter = new XmlSerializer(graph.GetType());
        formatter.Serialize(writer, graph);
    }

    public override void WriteEndObject(XmlDictionaryWriter writer) {
    }

    public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName) {
        var realType = Type.GetType("Client.Test, Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); //temporary solution
        var formatter = new XmlSerializer(realType);
        return formatter.Deserialize(reader);
    }

    public override bool IsStartObject(XmlDictionaryReader reader) {
        return true;//temporary solution
    }

}

我检查了从服务器到客户端的 SOAP,它几乎与 NetDataSerializer 呈现的相同.唯一的区别在于属性 xmlns="".

I checked SOAP that goes from server to client and it's almost the same as NetDataSerializer renders. The only difference is in attribute xmlns="".

Kai、Johann 感谢您的尝试.

Kai, Johann thanksfor your tries.

这篇关于WCF 和接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆