【问题标题】:WCF Service Serialization: The deserializer has no knowledge of any type that maps to this nameWCF 服务序列化:反序列化程序不知道映射到此名称的任何类型
【发布时间】:2010-10-27 01:02:54
【问题描述】:

我正在尝试构建 WCF 服务,但遇到了阻塞问题。我一直在谷歌搜索,但我无法取得任何进展。希望我在这里能有更多的运气。

假设我有一个这样定义的工作类:

[DataContract]
public class Job : IJob
{
    public Job(...)
    {
    }

    [DataMember]

    public string Example
    {
        get { return m_example; }
        set { m_example = value; }
    }
}

现在,我要做的就是这样

public void DoSomething()
{
    ExampleServiceProxy.ExampleClient proxy = new ExampleServiceProxy.ExampleClient();
    proxy.DoSomething(job);
}

在我的 Reference.cs 中,我添加了一些 ServiceKnownTypeAttribute,如下所示:

...
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(Job))]
void DoSomething(object job);

我的服务代码如下:

[ServiceContract]
public interface IExample
{
    [OperationContract]
    void DoSomething(IJob);
}

public class Example : IExample
{
    public void DoSomething(IJob job)
    {
        ...
    }
}

我需要在某处放置更多的 ServiceKnownTypeAttributes 吗?是否需要在服务端重新实现对象?

【问题讨论】:

    标签: c# wcf


    【解决方案1】:

    您必须将 ServiceKnownType 属性放在 Service Contract 接口上。

    [ServiceContract] 
    public interface IExample 
    { 
        [OperationContract] 
        [ServiceKnownType(typeof(Job))]
        void DoSomething(IJob); 
    } 
    
    public class Example : IExample 
    { 
        public void DoSomething(IJob job) 
        { 
            ... 
        } 
    } 
    

    【讨论】:

    • 我之前尝试过这样做,但我得到一个错误,它会引入循环依赖。这是因为 Job.cs 在另一个程序集中,我必须将它包含在 WCF 项目中(我认为)。
    • 好的。您别无选择,只能重构您的库以删除循环依赖项。将 ServiceContract、IJob 和 Job 定义全部放在一个库中。然后将服务器实现放在另一个可执行文件或库中,将客户端放在另一个可执行文件中。当您在 WCF 中编程时,您会习惯于创建大量库。
    • “反序列化程序不知道任何映射到此名称的类型。”是我用谷歌搜索的,这个解决方案对我有用。谢谢!
    【解决方案2】:

    您使用 IJob 界面有什么原因吗?我从未见过以这种方式实现 WCF。

    当我实现 WCF 时,我总是使用 DataContract,即 Job。我这样做是因为 DataContract 是双方之间的合同,并且没有任何行为。由于服务确实具有行为,因此使用接口是一个好主意。

    DataContract 也需要在服务端定义。因此,如果您要将 Job 移动到 Service 库,删除 IJob,删除 Client 中的现有引用并重新生成它,它将正常工作。

    这里是服务代码:

    [ServiceContract]
    public interface IExample
    {
        [OperationContract]
        void DoSomething(Job);
    }
    
    [DataContract]
    public class Job 
    {
        public Job(...)
        {
        }
    
        [DataMember]
    
        public string Example
        {
            get { return m_example; }
            set { m_example = value; }
        }
    }
    
    public class Example : IExample
    {
        public void DoSomething(Job job)
        {
            ...
        }
    }
    

    【讨论】:

    • 由于 Job 是 IJob 接口的实现,它真的有什么不同吗(根本不知道)。
    • 用“不要那样做”来回答问题是一种不好的形式,甚至没有尝试回答这个问题。如果你真的想说,那就等到你有足够的代表来添加评论。
    • @kkshin - 它会这样工作。唯一的区别是您需要编辑生成的 Reference.cs,这是我个人会避免的。无论哪种情况,Andrews 建议创建一个新库都是最好的解决方案,因为当服务接收到 WCF 消息时,它需要一个具体的类来反序列化它。
    • @kkshin - 我犯了一个错误,如果您按照我的建议使用 DataContract 并将其移动到服务库中,那么当您使用 Add Service Reference 生成客户端时(您正在这样做吗?),它将为您生成客户端的 Job 定义。因此,您不需要将 Job 移动到另一个库中。我会修正我的答案来说明这一点
    猜你喜欢
    • 2011-08-31
    • 2015-11-17
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    相关资源
    最近更新 更多