[MetadataType(typeof(MyModelMetadata))]
public class MyModel : MyModelBase {
... /* the current model code */
}
[DataContract]
public class MyModelMetadata {
[DataMember]
public string Name { get; set; }
}
或者,您可以通过执行问题中的建议来绕过整个问题:不要序列化域对象,而是创建自定义DTO对象并将其序列化 . 每当我使用实体框架时,我倾向于这样做,因为序列化这些可能很棘手 . 如果您的域对象内置了大量行为,这也是一种很好的方法 - 您可以清楚地分离"data being passed around"与"objects participating in my business logic."
4 回答
您可以使用
MetadataType
属性和元数据模型类,以便将注释与模型分开 .例如:
如果不向类添加任何序列化属性,并将其用作WCF服务 Contract 方法的一部分,则WCF将使用默认序列化规则来生成数据协定 . 这意味着该类将隐含地成为
[DataContract]
, bothget
和set
访问器将隐式变为[DataMember]
.您需要应用属性的唯一时间是您要覆盖默认行为,例如隐藏一些属性,应用名称空间等 . 只要默认行为符合您的需要,它就不是严格要求的 .
回应您的后续行动:
据我所知,没有完全外部的方法来改变给定类的
DataContractSerializer
的序列化行为;每个选项都要求序列化的类至少有一定程度的归属 . 正如@Yair Nevet在下面描述的那样,我将现有域对象转换为数据 Contract 的首选方法是MetadataType
属性 .或者,您可以通过执行问题中的建议来绕过整个问题:不要序列化域对象,而是创建自定义DTO对象并将其序列化 . 每当我使用实体框架时,我倾向于这样做,因为序列化这些可能很棘手 . 如果您的域对象内置了大量行为,这也是一种很好的方法 - 您可以清楚地分离"data being passed around"与"objects participating in my business logic."
您经常会遇到大量冗余代码,但它确实实现了对现有对象进行零更改的目标 .
WCF能够在没有属性的情况下序列化对象 . 这些属性允许自定义 . 例如,这两个类将通过DataContractSerializer进行相同的序列化:
值得一提的是,你真的应该用属性标记你的类 . 它们并不像你想象的那样“凌乱” . 它实际上可以让你在将来免于头痛 . 例如:
在前面的代码示例中,我明确设置了类和成员的名称 . 这将允许我重构名称而不破坏消费者代码 . 因此,如果某人决定我的 class 应该被命名为CustomerDetail而不是Customer,我仍然可以将该名称保留为Customer,以便我的服务的消费者继续工作 .
你总是可以使用DTO . 创建一个单独的类,其中包含序列化对象所需的所有内容 . 然后将您的域模型投影到DTO . 您可以使用AutoMapper之类的东西来简化此过程 .
Regarding Performance
除非每个类有数百个,可能是数千个,或者对象或者有大量属性,否则转换到DTO和从DTO转换的行为可能不是那么多的性能开销 .
如果您使用的是EF,并且没有对每个属性进行序列化,您甚至可以通过将EF查询直接投影到DTO来减少一些开销 .
这是一个戏剧性的案例,但我有(设计不佳)数据库模型,每种类型有50个属性 . 通过更改为只有我关心的10-15个属性的DTO,我几乎可以将WCF服务的性能提高一倍 .