【问题标题】:Can a POCO contain a constructor? [duplicate]POCO 可以包含构造函数吗? [复制]
【发布时间】:2014-08-25 08:18:46
【问题描述】:

POCO 可以包含构造函数吗?你能告诉我这门课是否正确吗?我还读到 POCO 必须有一个无参数的构造函数。这是正确的,为什么?如果我接受这个无参数构造函数,我的只读Id 属性就会出现问题。对我来说,如果这个属性必须是只读的,那么初始化它的唯一方法就是在构造函数中。

[DataContract]
public class MembershipUser
{
    public MembershipUser(Guid idValue)
    {
        this.Id = idValue;
    }

    [DataMember]
    public virtual readonly Guid Id { get; set; }

    [DataMember]
    public virtual string UserName { get; set; }

    [DataMember]
    public virtual string Email { get; set; }
}

【问题讨论】:

  • 会编译吗?是的。我们知道它是否适合您的需求吗?当然不是。就目前而言,这不是一个好问题。
  • 如果您在实体框架代码优先的上下文中指代 POCO,那么不,实体框架将不支持您的类。你需要一个无参数的构造函数。
  • WCF 也不会,它基于您所定位的 [DataContract] 属性。
  • POCO 不是严格定义的术语(即 SO 定义的变体在链接 duplicate question 中)。所以“POCO 可以有 XXXX”不能比链接的问题更好地回答。如果您使用特定框架 POCO 可能意味着“普通对象”的某些特定子集,并且可能需要也可能不需要特定功能作为默认构造函数的存在或不存在。如果需要,请随时单独询问更具体的版本。
  • 旁注:我个人不会将此类对象称为“POCO”,因为您的代码意味着继承并且感觉超出了“普通”对象的范围。

标签: c# poco


【解决方案1】:

POCO 对象可以包含其他构造函数,但反序列化需要默认构造函数,因为该过程会尝试创建对象的默认实例,然后设置属性。

经过一些研究,似乎 datacontract 序列化程序不使用甚至不调用默认构造函数。使用它,您可以排除默认 ctor 并仍然序列化您的 POCO。是否应该是您和您的团队必须决定的实施细节。

DataContractSerializer 测试:

[Test]
public void SerializerTest()
{
    var s = new SerializeMe(2);
    s.Name = "Test";
    DataContractSerializer dcs = new DataContractSerializer(typeof(SerializeMe));
    Stream ms = new MemoryStream();
    var writer = XmlWriter.Create(ms);
    Assert.DoesNotThrow(() => dcs.WriteObject(writer, s));
    writer.Close();

    ms.Position = 0;
    var reader = new StreamReader(ms);
    var xml = reader.ReadToEnd();
    Console.WriteLine(xml);
}

[Test]
public void DeserializeTest()
{
    var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><SerializeMe xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/Test\"><Id>2</Id><Name>Test</Name></SerializeMe>";
    DataContractSerializer dcs = new DataContractSerializer(typeof(SerializeMe));            
    XmlReader reader = XmlReader.Create(new StringReader(xml));
    var obj = dcs.ReadObject(reader) as SerializeMe;
    Assert.AreEqual(obj.Name, "Test");
}

[DataContract]
public class SerializeMe
{
    public SerializeMe(int id)
    {
        this.Id = id;
    }
    [DataMember]
    public int Id { get; private set; }
    [DataMember]
    public string Name { get; set; }
}

【讨论】:

  • 更正我,但我仍然可以编写自己的反序列化过程。
  • @B413 是的,您可以这样做,但您为什么要这样做? .Net 中内置了一堆序列化机制,无需重新发明轮子。
  • 我喜欢这个“没有必要重新发明轮子”。相信我,总是有理由重新发明轮子。最好的例子可能是 .NET 框架。我认为这句话应该从 IT ......和大多数其他工程工作中剔除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
相关资源
最近更新 更多