这是我在WCF服务中使用的DLL中的类定义之一。
[DataContract]
public class ScenarioXML
{
[DataMember(Order = 1)]
public long? TNRScenario { get; set; }
[DataMember(Order = 2)]
public long? TNRProject { get; set; }
[DataMember(Order = 3)]
public int? Priority { get; set; }
// ...
[DataMember(Order = 19)]
public List<ScenarioAssetXML> ScenarioAssets { get; set; }
[DataMember(Order = 20)]
public List<CalendarXML> Calendars { get; set; }
[DataMember(Order = 21)]
public ScenarioTriggerCollectionXML ScenarioTriggerCollection { get; set; }
}
我正在使用DataContract而不是ProtoContract,因此我可以通过WSDL将此类公开给Silverlight项目,并且仍然使用Protobuf-net进行序列化。
现在,当我在WCF服务中使用以下代码时,原始“方案”和“restoredModel”是相同的。
MemoryStream msTestString = new MemoryStream();
Serializer.Serialize<ScenarioXML>(msTestString, scenario);
string memento = Convert.ToBase64String(msTestString.ToArray());
byte[] byteAfter64 = Convert.FromBase64String(memento);
MemoryStream afterStream = new MemoryStream(byteAfter64);
ScenarioXML restoredModel = Serializer.Deserialize<ScenarioXML>(afterStream);
但是,当我在Silverlight中使用相同的代码时,TNRScenario值为null。 同样,ScenarioAssets列表中对象的TNRScenarioAsset属性为null。
[DataContract]
public class ScenarioAssetXML
{
[DataMember(Order = 1)]
public long? TNRScenarioAsset { get; set; }
[DataMember(Order = 2)]
public long? TNRScenario { get; set; }
[DataMember(Order = 3)]
public string Asset { get; set; }
[DataMember(Order = 4)]
public string Action { get; set; }
}
当我将第一个属性设为字符串时,它会在(反)序列化后完全消失。当我将一个虚拟bool作为第一个属性时,bool就在那里,但第二个属性(在本例中为ScenarioAssets)仍然为null。这里有一些奇怪的事情......
我做错了,还是这个错误?
编辑: 你是马克!订单在WSDL生成的代码中搞砸了。
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="ScenarioXML", Namespace="http://schemas.datacontract.org/2004/07/DataCollectionDLL")]
public partial class ScenarioXML : object, System.ComponentModel.INotifyPropertyChanged {
private System.Nullable<long> TNRScenarioField;
private System.Nullable<long> TNRProjectField;
private System.Nullable<int> PriorityField;
//...
[System.Runtime.Serialization.DataMemberAttribute()]
public System.Nullable<long> TNRScenario {
get {
return this.TNRScenarioField;
}
set {
if ((this.TNRScenarioField.Equals(value) != true)) {
this.TNRScenarioField = value;
this.RaisePropertyChanged("TNRScenario");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(Order=1)]
public System.Nullable<long> TNRProject {
get {
return this.TNRProjectField;
}
set {
if ((this.TNRProjectField.Equals(value) != true)) {
this.TNRProjectField = value;
this.RaisePropertyChanged("TNRProject");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(Order=2)]
public System.Nullable<int> Priority {
get {
return this.PriorityField;
}
set {
if ((this.PriorityField.Equals(value) != true)) {
this.PriorityField = value;
this.RaisePropertyChanged("Priority");
}
}
}
//...
但是,我不确定如何正确实现该分类?我在WCF服务中创建它,但这似乎混淆了编译器。得到以下错误:
然后在Silverlight项目中尝试了它,它编译得很好,但是没有解决问题。结果是一样的。
我创建的部分课程:
namespace DataCollectionDLL
{
[ProtoContract]
[ProtoPartialMember(1, "TNRScenario")]
[ProtoPartialMember(2, "TNRProject")]
[ProtoPartialMember(3, "Priority")]
//...
[ProtoPartialMember(21, "ScenarioTriggerCollection")]
partial class ScenarioXML
{
}
}
答案 0 :(得分:0)
听起来你使用了WSDL生成的代理;因为protobuf-net 真的非常关心数字是什么,所以WSDL有时可以快速和松散地使用它们。如果我能看到WSDL生成的代理类(在.designer.cs
中),那将非常有帮助,但我将假设这就是问题所在。幸运的是,大多数代码生成器都使用partial class
,因此您可以将拥有 partial class
添加到单独的文件中,以便将额外信息添加到相同类型中,特别是:更多属性。例如:
namespace The.Same.Namespace
{
[ProtoContract]
[ProtoPartialMember(1, "TNRScenario")]
[ProtoPartialMember(2, "TNRProject")]
// ...
[ProtoPartialMember(21, "ScenarioTriggerCollection")]
partial class ScenarioXML { }
}
这将由编译器合并到ScenarioXML
类中,并且应该允许protobuf-net为每个属性使用正确的数字标识符。