从 Xml 反序列化对象后执行自定义类型的代码 [英] Execute code to custom type after deserializing an object from Xml

查看:28
本文介绍了从 Xml 反序列化对象后执行自定义类型的代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对使用 XmlSerializer.Deserialize 创建的 CustomType 的所有实例进行一些操作

I want do some manipulation on all instances of a CustomType that got created with an XmlSerializer.Deserialize

最好的方法是作为构造函数传入,但PostSerialization"可以正常工作.在此示例中,我需要根据 XmlSerializer 上下文将对象传递给我的 CustomType.

The best way would be to pass in as a constructor, but "PostSerialization" would work just fine. In this example, I need to pass in an object to my CustomType based from the XmlSerializer context.

public class CustomType : IXmlSerializable
{
    public CustomType()
        : this(null)
    {
    }

    public CustomType(Object somethingImportant)
    {
    }

    public void ReadXml(System.Xml.XmlReader reader) { ... }
    public void WriteXml(System.Xml.XmlWriter writer) { ... }
}

...

Object somethingImportant = 12345; // I need to pass this to *all* CustomType
var serializer = new XmlSerializer(typeof(MyType));
var reader = new StringReader(str);
return serializer.Deserialize(reader) as MyType;

XmlAttributeOverrides 是个好主意,但MyType"相当复杂,我无法通过所有可能的 XmlElement 来自定义创建 CustomType.

XmlAttributeOverrides is a good idea, but "MyType" is quite complex, I can't go through all the possible XmlElement to custom create the CustomType.

推荐答案

您可以将 Object somethingImportant 设为线程静态变量,并在非 null 时在构造函数中使用它,如下所示:

You could make the Object somethingImportant a thread-static variable, and use it in the constructor when non-null, like so:

public class CustomType 
{
    [ThreadStatic]
    static object deserializationObject;

    public static IDisposable SetDeserializationObject(object deserializationObject)
    {
        return new DeserializationObjectValue(deserializationObject);
    }

    sealed class DeserializationObjectValue : IDisposable
    {
        object oldValue;

        public DeserializationObjectValue(object value)
        {
            this.oldValue = deserializationObject;
            deserializationObject = value;
        }

        int disposed = 0;

        public void Dispose()
        {
            // Dispose of unmanaged resources.
            if (Interlocked.Exchange(ref disposed, 1) == 0)
            {
                Dispose(true);
            }                // Suppress finalization.  Since this class actually has no finalizer, this does nothing.
            GC.SuppressFinalize(this);
        }

        void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Free any other managed objects here.
                deserializationObject = oldValue;
                oldValue = null;
            }
        }
    }

    private CustomType(object deserializationObject)
    {
        if (deserializationObject != null)
        {
            // Handle as needed.
        }
    }

    public CustomType() : this(deserializationObject)
    {
    }
}

然后在反序列化时设置它:

Then set it when deserializing like so:

        using (CustomType.SetDeserializationObject("this is a runtime value"))
        {
            var serializer = new XmlSerializer(typeof(MyType));
            var reader = new StringReader(str);
            var myType = serializer.Deserialize(reader) as MyType;
        }

通过仅在一次性包装器中公开设置 deserializationObject,您可以确保它永远不会被永久遗留.

By publicly setting the deserializationObject only within the disposable wrapper you ensure it's never left around permanently.

这篇关于从 Xml 反序列化对象后执行自定义类型的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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