2

这是我在 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 值为空。同样,ScenarioAssets 列表中对象的 TNRScenarioAsset 属性为空。

[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; }
}

当我将第一个属性设为字符串时,它在(反)序列化后完全消失。当我将虚拟布尔值作为第一个属性时,布尔值就在那里,但第二个属性(在本例中为 ScenarioAssets)仍然为空。这里发生了一些奇怪的事情......

我做错了什么,还是这是一个错误?

编辑:你是对的,马克!订单在 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\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
    {
    }
}
4

1 回答 1

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

于 2013-09-04T09:20:46.930 回答