动态忽略数据成员进行序列化 [英] Dynamically ignore data members from getting serialized

查看:93
本文介绍了动态忽略数据成员进行序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个现有的WCF服务,该服务使用多个DataContracts。我们要基于设备修改序列化,以便从移动设备访问时,服务应仅序列化一些重要数据成员(不是全部)

We have an existing WCF service which uses several DataContracts. We want to modify the serialization based on the device, so that when accessed from mobile devices, the service should serialize only some important data members(not all)

我们有2此处的选项


  1. 为不同类型的
    设备创建单独的操作和数据合同

  2. 混乱并进行实际的xml序列化,并禁止根据设备创建
    不必要的元素

第一种选择是因为它在将来会引入很多冗余代码问题

We don't want to go with the first option since it introduces a lot of redundant code problems in the future

小型研究表明,我们需要使用IXmlSerializable并覆盖readXML()和writeXML()方法。但是同时,我在某个地方看到不应将DataContract和IXmlSerializable一起使用

Small research showed that we need to use IXmlSerializable and override the readXML() and writeXML() methods. But at the same time, I have seen somewhere that DataContract and IXmlSerializable should not be used together

任何与实际序列化有关的示例都将受到赞赏。

Any example to mess with actual serialization is greatly appreciated .

[DataContract]
public class TokenMessage
{
    string tokenValue;
    string extraValue;
    [DataMember]
    public string Token
    {
        get { return tokenValue; }
        set { tokenValue = value; }
    }
    [DataMember]
    public string Extra 
    {
        get { return extraValue; }
        set { extraValue = value; }
    }
}

现在,当我访问返回典型来自移动设备的TokenMessage数据协定,我不希望序列化额外数据成员,即当我为操作协定提供不同的参数时,它应该能够序列化一些/所有数据成员(取决于动作)

Now when i access the service which returns a typical TokenMessage data contract, from a mobile device, i don't want the "Extra" data member to be serialized i.e. When I supply a different argument to the operation contract, it should be able to serialize some/all the data members(depending on the action)

PS:目前,请忽略设备检测部分。假设我们在操作合同中有一个论点,它可以帮助我们识别设备

PS: For now please ignore the device detection part. Lets assume we have an argument in the operation contract, which helps us identify the device

推荐答案

我不相信某些变体@Pranav Singh的答案并不是一个更好的设计,但这不是您的问题...

I'm not convinced that some variant of @Pranav Singh's answer isn't a better design, but that's not your question...

正如您在.NET中的注释属性中所提到的,它在设计上是静态的。这意味着动态添加/删除 [DataMember] 并不是一个好选择。有可能的。有一些选项,例如使用Reflection.Emit通过元数据更改来重新创建实例(请参见是否可以在C#中动态添加属性?),但是所有这些路由都很复杂。

As you mentioned in a comments attributes in .NET are static by design. This means dynamically adding/removing [DataMember] isn't a good option. It is possible. There are options like using Reflection.Emit to recreate the instance with the meta data changes (see all the answers to Can attributes be added dynamically in C#?) but all of those routes are complicated.

我看到两个合理的选择:

I see two reasonable options:

1)实施该服务的IParameterInspector 。在 AfterCall ()方法中您可以检查并更改在序列化之前返回给客户端的参数 。有一些工作可以使用反射来动态确定参数类型并设置其值,但这并不复杂。这是更好的设计,可以在许多合同或服务之间重用行为。 Carlos Figueira的博客

1) Implement an IParameterInspector for the service. In the AfterCall() method you could inspect and alter the parameters being returned to the client before they are serialized. There is some work to use reflection to dynamically determine the parameter types and set their values, but its not complicated. This is the better design that enables reuse of the behavior across many contracts or services. Carlos Figueira's blog is the best source for WCF extension examples.

2)使用 [OnSerializing] [OnSerialized] 事件。在[DataContract]中,您可以临时更改序列化期间返回的属性。 事件实际上是为了启用初始化而设计的,因此,此解决方案有点麻烦。此解决方案也不是线程安全的。但是它确实将代码包含在DataContract类中,并且可以快速解决问题(我认为您正在寻找快速问题)。

2) Use the [OnSerializing] and [OnSerialized] events. In the [DataContract] you could temporarily alter what the properties are returning during serialization. The events are actually designed to enable initialization and as such this solution is a bit of a hack. This solution is also not thread safe. But it does keep the code contained to the DataContract class and solves the problem quickly (and I think you are looking for quick).

解决方案#2可能类似于:

Solution #2 mights look something like:

[DataContract]
public class TokenMessage
{
    string tokenValue;
    string extraValue;

    bool enableExtraValue = true;

    [DataMember]
    public string Extra 
    {
        get { 
                if (enableExtraValue) 
                      return extraValue;
                return null; 
            }
        set { extraValue = value; }
    }

    [OnSerializing()]
    internal void OnSerializingMethod(StreamingContext context)
    {
        enableExtraValue = false;
    }

    [OnSerialized()]
    internal void OnSerializedMethod(StreamingContext context)
    {
        enableExtraValue = true;
    }
}

解决方案2是一个快速解决方案(即我认为您正在寻找)。

Solution #2 is a quick fix (which is what I think you are looking for).

解决方案1是更好的设计。

Solution #1 is the better design.

这篇关于动态忽略数据成员进行序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆