【问题标题】:WCF How to make DataContract for an external classWCF如何为外部类制作DataContract
【发布时间】:2016-01-05 09:00:09
【问题描述】:

我想在我的 wcf 服务中使用来自其他解决方案的现有类。所以我必须向它添加 DataContract。

实现这一目标的最佳方法是什么? 我听说 DataContract Surrogate 是一种方法,但我真的不明白我必须如何使用它。

现有类

public class Person
{
    public string Name{get; set;}
    public long Size{get; set;}
    public DateTime Birthdate{get; set;}

    public Person(string name, long size, DateTime birthdate)
    {
        this.Name = name;
        this.Size = size;
        this.Birthdate = birthdate;
    }
}

这就是外部类的样子。有人可以给我举个例子,我必须如何将它放在我的 wcf 服务中。

编辑

我有一个 Windows 服务,其中我有这个类 Person。我在 Windows 服务中的方法返回一个人员列表,所以 List<Person>。现在我正在尝试将此列表传递给我的 wcf 服务。因此我需要将 DataContract 添加到该类。我是否必须在 wcf 服务中编写一个新课程,或者我可以从 windows 服务中移交我的课程。

【问题讨论】:

  • 如果您可以更改Person,则只需添加[DataContract]。仅当您无法更改类时才需要 DataContract 代理。
  • 这个类来自另一个解决方案。如果我将它集成到我的 wcf 服务中会是什么样子?

标签: c# wcf


【解决方案1】:

我刚刚投票for Tom Redfern solution,但为了使答案完整,我会添加更多链接,以便作者决定是否真的想使用代理。在非常相似的question 中与汤姆斯的建议非常相似被投票。您可以浏览 cmets 和答案中的链接。

您可以自己结帐what surrogates are and how to use them。从技术上讲是的,您可以使用它来模拟和代理来自 3rd 方程序集的现有类 (here is very detailed example)。

为什么问题作者会出现这种情况?我认为只有当真实案例不是问题中的 Person 类,而是真正更复杂的情况时。

代理已经存在了一段时间,甚至在 WCF 之前,他们的想法很简单:用另一种类型 B(“代理”)替换一个类型 A,它是要序列化的对象图的一部分。我们想要这样做的主要原因是因为类型 A 根本不可序列化,或者因为它没有我们想要的序列化格式,所以我们使用代理来更改它。第一种情况很简单——有时你有一个来自第 3 方或遗留库的类型,它不能被修改以适应序列化,但它是你想要在客户端和服务器之间交换的对象图的一部分。一种可能的解决方案是在仅包含需要序列化的数据的数据传输对象 (DTO) 中复制图形。然而,有时这可能不是最好的方法(类型太多、在 DTO 和具有业务逻辑的对象之间转换的成本很高等),因此代理可能是一种出路。第二种情况(想要改变序列化格式)并不经常发生,但是在某些场景中,用户想要改变一个类型的序列化方式。

【讨论】:

  • + 1 感谢您提供这个答案 - 老实说,我不知道代理功能,坦率地说,他们从 3.0 开始就成为 WCF 的一部分。我猜它们还没有被许多解决方案轻易采用,尽管从链接中我可以同意这也可以满足 OPs 要求,尽管以增加复杂性为代价。
【解决方案2】:
[DataContract]
public class Person
{
    [DataMember] public string Name { get; set; }
    [DataMember] public long Size { get; set; }
    [DataMember] public DateTime Birthdate { get; set; }

    public Person(string name, long size, DateTime birthdate)
    {
        this.Name = name;
        this.Size = size;
        this.Birthdate = birthdate;
    }
}

【讨论】:

  • 在哪里提到该类来自其他解决方案?
  • 我不确定你的意思。您将在其他解决方案中更改类以添加 WCF 属性。如果你不能这样做,那么你需要像我最初所说的那样创建一个代理。
  • 好吧,我想我没有很好地解释我在做什么。我正在将一个 List 从我的 Windows 服务传递给我的 wcf 服务。现在我需要给 Object DataContract。对象在 windows 服务中定义。你明白我想要的吗?
  • 所以在windows服务中将WCF属性添加到Object中。
  • 我强烈反对 OP 应该通过使用 System.ServiceModel 的属性以某种方式标记 Person 类型来解决此问题 - 没有关于此类型来自何处、更改频率等的信息。定义一个代表 Person 类型的单独数据协定会好得多。
【解决方案3】:

首先,Person 类型是在程序集中定义的吗?或者它被捆绑到一个exe中?如果是后者,那么尽管您可以添加对 exe 的二进制引用,但它是 considered bad practice

如果它是在程序集中定义的,您可以只使用 Person 类型作为 WCF 服务中的数据协定类型。您只需创建对程序集的二进制引用,此类型将通过 DataContractSerializer 跨服务边界进行序列化。

正如 MS 所说:

默认情况下,DataContractSerializer 会推断数据协定并 序列化所有公开可见的类型。所有公共读/写 该类型的属性和字段被序列化

但是,您是否应该这样做是另一个问题。

在 WCF 项目中定义 Person 类型,公开该类型(或该类型的 List<>,根据您的 cmets),然后让客户端将其 Person 类型映射到 Person 类型会容易得多调用服务时在服务上定义。

如果类型包含在 exe 中,这确实是唯一对您开放的选项。即使它在 dll 中,您仍然应该这样做,因为它将服务与使用者分离。依赖方向应该是消费者 -> 服务而不是服务 -> 消费者。

如果你想避免编写映射代码,有很多object mappers 可用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多