Protobuf-Net Silverlight:DataContract类具有null或缺少的属性

时间:2013-09-04 09:09:09

标签: silverlight properties null wsdl protocol-buffers

这是我在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服务中创建它,但这似乎混淆了编译器。得到以下错误:

  • 错误6'DataCollectionDLL.ScenarioXML'不包含'TNRScenario'的定义,并且没有可以找到接受类型'DataCollectionDLL.ScenarioXML'的第一个参数的扩展方法'TNRScenario'(您是否缺少using指令或程序集引用?)
  • 错误2无法将类型'DataCollectionDLL.ScenarioXML [c:\ Projects \ Flowcontrol 1.7.1.1 \ flowcontrolFC.Web \ Libraries \ DataCollectionDLL.dll]'转换为'DataCollectionDLL.ScenarioXML [C:\ Projects \ Flowcontrol 1.7.1.1 \ flowcontrolFC.Web \ DAL \ DataCollectionClasses \ ScenarioXML.cs(31)]'

然后在Silverlight项目中尝试了它,它编译得很好,但是没有解决问题。结果是一样的。

我创建的部分课程:

namespace DataCollectionDLL
{
    [ProtoContract]
    [ProtoPartialMember(1, "TNRScenario")]
    [ProtoPartialMember(2, "TNRProject")]
    [ProtoPartialMember(3, "Priority")]
    //...
    [ProtoPartialMember(21, "ScenarioTriggerCollection")]
    partial class ScenarioXML
    {
    }
}

1 个答案:

答案 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为每个属性使用正确的数字标识符。