gpt4 book ai didi

c# - 重命名标有 DataMemberAttribute 的类属性

转载 作者:行者123 更新时间:2023-11-30 22:44:23 26 4
gpt4 key购买 nike

其实我有这样一个类

[DataContract]
public class Item : IExtensibleDataObject
{
[Browsable(false)]
public virtual ExtensionDataObject ExtensionData { get; set; }

[DataMember]
public string ID { get; set; }

[DataMember]
public string Name { get; set; }

public Item()
: this(String.Empty, String.Empty)
{ }

public Item(string id, string name)
{
ID = id ?? String.Empty;
Name = name ?? String.Empty;
}
}

您可以轻松地对其进行序列化和反序列化。但现在是困难的部分:

我必须将属性 Name 重命名为 FullName 并且每个新的 xml 序列化文件都应该带有 FullName 而它仍然是可能的读入旧文件。

将新属性名称放入新文件非常容易。只需重命名属性即可。

为了兼容性,我会用 [DataMember(Name="Name")] 标记新属性名称,但在这种情况下,如果我将此类写回到文件中,我会写入旧名称。

DataContract 中存在一些东西,我可以在其中标记我的属性 FullName 可能是两次

[DataMember(Name="Name")]
[DataMember]
public string FullName { get; set}

或者是否有任何其他机制可以证明这两个值都可以写入其中,但只有一个会在回写时出现?

我能想到的唯一方法是创建一个类 LegacyItem,它没有任何函数或类似的东西,但实现了旧的 DataContract。此外,还有一些隐式/显式运算符可将我的 LegacyItem 转换为 Item。最后但并非最不重要的反序列化我必须做一些测试(也许只是一个简单的 try/catch)来找出我应该告诉 DataContractSerializer 读入文件的类.

因此,即使这种方法可行,对于这项任务来说听起来有点过于复杂,我想知道框架中是否已经有可用的东西可以使这项任务更容易一些。

最佳答案

如果你不介意在你的类中有一些过时的代码(无论如何它会比你建议的整个第二类代码少)那么你可以这样做:

[DataContract]
public class Item : IExtensibleDataObject
{
public virtual ExtensionDataObject ExtensionData { get; set; }

[DataMember]
public string ID { get; set; }

[DataMember(Name = "Name", EmitDefaultValue = false)]
private string _obsoleteName { get { return null; } set { if(value != null) FullName = value; } }

[DataMember]
public string FullName {get; set;}

public Item()
: this(String.Empty, String.Empty)
{ }

public Item(string id, string name)
{
ID = id ?? String.Empty;
FullName = name ?? String.Empty;
}
}

可以读入旧的 XML,反序列化将正确分配给您的新属性。然后在序列化时,只有新属性将通过 set 访问器序列化为 FullName。序列化时,旧属性始终返回 null,并且不会向序列化的 XML 发出事件。

您还可以将过时的属性标记为私有(private),这样它在类之外是不可见的。

一些提示,我更喜欢不对 DataMember 属性使用自动属性。事实上,我通常将支持字段标记为 DataMember。最好始终为 DataMember 属性包含可选的 Name 参数。我承认我自己并不总是这样做,但这是一个很好的做法,因为如果您在 Visual Studio 中重构 -> 重命名属性或字段,您就不会意外地违反契约(Contract)。

更新

OP Oliver 自己提出了另一种解决方案......对于那些感兴趣的人来说,这是看起来像的东西。

[DataContract]
public class Item : IExtensibleDataObject
{
public virtual ExtensionDataObject ExtensionData { get; set; }

[DataMember]
public string ID { get; set; }

[DataMember(Name = "Name", EmitDefaultValue = false)]
private string _obsoleteName;

[DataMember]
public string FullName {get; set;}

public Item()
: this(String.Empty, String.Empty)
{ }

public Item(string id, string name)
{
ID = id ?? String.Empty;
FullName = name ?? String.Empty;
}

[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
if(_obsoleteName != null && FullName == null)
{
//upgrade old serialized object to new version
//by copying serialized Name field to newer FullName
FullName = _obsoleteName;

//set _obsoleteName to null so that it stops serializing
_obsoleteName = null;
}
}
}

关于c# - 重命名标有 DataMemberAttribute 的类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3447565/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com