如何序列化Control等复杂类型对象

1 篇文章 0 订阅

.NET Framework提供了将对象序列化和反序列化的能力。利用这种机制,我们可以将对象实例的状态存储到存储媒体上,也可以将对象从一个地方传递到另一个地方。

.NET Framework提供了一些用于序列化的类。一个是BinnaryFormatter,它使用二进制格式序列化对象。另一个是SoapFormatter,它使用soap格式(基于XML格式)序列化对象。还可以使用XMLSerializer将对象序列化成XML格式。然而这种序列化机制是有一定限制的,它只能序列化特定的对象。这些对象要么是从MarshalByRefObject派生的对象,要么是标记为Serializable的简单类型对象。像System.Windows.Forms.Control这类复杂的对象就不能被支持。

今天我要介绍的是如何序列化System.Windows.Forms.Control这类复杂的对象。在介绍之前,我们先看看序列化和反序列化的流程。

序列化反序列化流程图

分离出复杂的逻辑,最简单的逻辑只有两步,第一步-序列化过程:将内存中的对象数据用XML格式的数据表示。第二步-反序列化过程:构造一个新对象,并将XML格式表示的数据赋值给这个新的对象。这样,原始对象和新构造的对象会有同样的数据,即表示同一种状态。

经常使用VS2005,VS2008等IDE的开发人员,特别是做过Design Time开发的开发人员可能会注意到,这个过程其实和IDE自动生成控件代码的过程相似。

IDE设计编译流程

在使用IDE的过程中,我们在Design环境中给Form拖一个TextBox控件,IDE会在Design环境中创建一个TextBox控件,并生成相关C#或者VB等格式的代码。这个阶段叫设计时(DesignTime)。这个过程类似我们刚才讲到的第一步-序列化过程。而我们点击运行的时候,这些文本格式的代码又会被编译运行,根据编译的代码生成一个新TextBox控件在Form上显示。这个阶段叫运行时(RunTime)。这个过程就类似我们刚才讲到的第二步-反序列化过程。可以看出来,IDE在DesignTime下是将控件实例序化成C#或VB等代码。而在RunTime下是将代码编译运行,生成新的控件实例来保持DesignTime下设计的状态与RunTime下显示的状态一致。事实上,这也是序列化和反序列化的一种方式。

既然IDE的这个过程也是序列化和反序列化的方式,那么IDE是怎么实现复杂控件序列化和反序列化的呢?这可能需要另外一篇文章才能讲清楚,这里暂不研究。不过我们可以知道,IDE是有能力做这件事情的。我们也可以利用IDE的这种能力,来实现复杂控件的序列化和反序列化。

下面这段代码演示了如何利用IDE的这种能力序列化一个Object。

 

//==============================================================================
//  File Name   :   CodeDomSerializationHelper.cs
//
//  Copyright (C) 2007 KevinShan. All rights reserved.
//==============================================================================

// <fileinformation>
//   <summary>
//     Define the CodeDomSerializationHelper to do some serialization works.
//   </summary>
//   <author name="Kevin Shan" mail=">
//   <seealso ref=""/>
// </fileinformation>

// <history>
//   <record date="20070528" author="Kevin Shan" revision="1.00.000">
//     Create this file.
//   </record>
// </history>

using System;
using System.Collections;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.IO;
using System.Windows.Forms;
using System.ComponentModel;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;

namespace Test
{
    #region The CodeDomSerializationHelper class

    /// <summary>
    ///   Define the CodeDomSerializationHelper to do some serialization works.
    /// </summary>
    internal static class CodeDomSerializationHelper
    {
        #region Nested Types

        #region The DefaultCodeDomDesignerLoader class

        /// <summary>
        ///   Inherits from CodeDomDesignerLoader.
        /// </summary>
        private class DefaultCodeDomDesignerLoader : CodeDomDesignerLoader
        {
            #region Instance Data

            /// <summary>
            ///   Save the data of code compilie unit.
            /// </summary>
            private CodeCompileUnit _codeCompileUnit;

            #endregion

            #region Properties

            private CodeDomProvider _codeDomProvider;
            /// <summary>
            ///   Gets the <see cref="P:System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.CodeDomProvider"></see> this designer loader will use.
            /// </summary>
            /// <value></value>
            /// <returns>
            ///   The <see cref="P:System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.CodeDomProvider"></see> this designer loader will use
            /// </returns>
            protected override CodeDomProvider CodeDomProvider
            {
                get
                {
                    if (this._codeDomProvider == null)
                    {
                        this._codeDomProvider = new Microsoft.CSharp.CSharpCodeProvider();
                    }
                    return this._codeDomProvider;
                }
            }

            private ITypeResolutionService _typeResolutionService;
            /// <summary>
            ///   Gets the type resolution service to be used with this designer loader.
            /// </summary>
            /// <value></value>
            /// <returns>
            ///   An <see cref="T:System.ComponentModel.Design.ITypeResolutionService"></see> that the CodeDOM serializers will use when resolving types.
            /// </returns>
            protected override ITypeResolutionService TypeResolutionService
            {
                get
                {
                    if (this._typeResolutionService == null)
                    {
                        this._typeResolutionService = new DefaultTypeResolutionService(this.LoaderHost);
                    }
                    return this._typeResolutionService;
                }
            }

            #endregion

            #region Methods

            /// <summary>
            ///   Parses the text or other persistent storage and returns a <see cref="T:System.CodeDom.CodeCompileUnit"></see>.
            /// </summary>
            /// <returns>
            ///   A <see cref="T:System.CodeDom.CodeCompileUnit"></see> resulting from a parse operation.
            /// </returns>
            protected override System.CodeDom.CodeCompileUnit Parse()
            {
                CodeTypeDeclaration designedClass = new CodeTypeDeclaration("AutoGeneratedClass");
                designedClass.BaseTypes.Add(typeof(Form));

                CodeNamespace nameSpace = new CodeNamespace("GrapeCity.AutoGeneratedCode");
                nameSpace.Types.Add(designedClass);

                CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
                codeCompileUnit.Namespaces.Add(nameSpace);

                return codeCompileUnit;
            }

            /// <summary>
            ///   Writes compile-unit changes to persistent storage.
            /// </summary>
            /// <param name="unit">
            ///   The <see cref="T:System.CodeDom.CodeCompileUnit"></see> to be persisted.
            /// </param>
            protected override void Write(System.CodeDom.CodeCompileUnit unit)
            {
                this._codeCompileUnit = unit;
            }

            /// <summary>
            ///   Generates the source code.
            /// </summary>
            /// <returns></returns>
            public string GenerateCode()
            {
                return this.GenerateCode(null);
            }

            /// <summary>
            ///   Generates the source code.
            /// </summary>
            /// <param name="codeDomProvider">
            ///   A <see cref="CodeDomProvider"/> indicates the code DOM provider.
            /// </param>
            /// <returns>
            ///   A <b>string</b> value indicates the source code.
            /// </returns>
            public string GenerateCode(CodeDomProvider codeDomProvider)
            {
                this.Flush();

                if (this._codeCompileUnit != null)
                {
                    CodeGeneratorOptions options = new CodeGeneratorOptions();
                    options.BracingStyle = "C";
                    using (StringWriter sw = new StringWriter())
                    {
                        if (codeDomProvider == null)
                        {
                            this.CodeDomProvider.GenerateCodeFromCompileUnit(this._codeCompileUnit, sw, options);
                        }
                        else
                        {
                            codeDomProvider.GenerateCodeFromCompileUnit(this._codeCompileUnit, sw, options);
                        }
                        return sw.ToString();
                    }
                }

                return string.Empty;
            }

            #endregion
        }

        #endregion

        #region The DefaultTypeResolutionService class

        /// <summary>
        ///   This service resolved the types and is required when using the CodeDomHostLoader.
        /// </summary>
        private class DefaultTypeResolutionService : ITypeResolutionService
        {
            #region Instance Data

            /// <summary>
            ///   A <see cref="IDesignerLoaderHost"/> value indicates the designer loader host.
            /// </summary>
            private IDesignerLoaderHost _designerLoaderHost;

            /// <summary>
            ///   A type cache pool to cache the finded type.
            /// </summary>
            private Dictionary<string, Type> _typeCachePool = new Dictionary<string, Type>();

            #endregion

            #region Constructor

            /// <summary>
            ///   Initializes a new instance of the <see cref="DefaultTypeResolutionService"/> class.
            /// </summary>
            /// <param name="designerLoaderHost">
            ///   A <see cref="IDesignerLoaderHost"/> value indicates the designer loader host.
            /// </param>
            public DefaultTypeResolutionService(IDesignerLoaderHost designerLoaderHost)
            {
                if (designerLoaderHost == null)
                {
                    throw new ArgumentNullException();
                }
                this._designerLoaderHost = designerLoaderHost;
            }

            #endregion

            #region ITypeResolutionService Members

            /// <summary>
            ///   Gets the requested assembly.
            /// </summary>
            /// <param name="name">
            ///   The name of the assembly to retrieve.
            /// </param>
            /// <param name="throwOnError">
            ///   true if this method should throw an exception if the assembly cannot be located;
            ///   otherwise, false, and this method returns null if the assembly cannot be located.
            /// </param>
            /// <returns>
            ///   An instance of the requested assembly, or null if no assembly can be located.
            /// </returns>
            public Assembly GetAssembly(AssemblyName name, bool throwOnError)
            {
                throw new NotSupportedException();
            }

            /// <summary>
            ///   Gets the requested assembly.
            /// </summary>
            /// <param name="name">
            ///   The name of the assembly to retrieve.
            /// </param>
            /// <returns>
            ///   An instance of the requested assembly, or null if no assembly can be located.
            /// </returns>
            public Assembly GetAssembly(AssemblyName name)
            {
                throw new NotSupportedException();
            }

            /// <summary>
            ///   Gets the path to the file from which the assembly was loaded.
            /// </summary>
            /// <param name="name">
            ///   The name of the assembly.
            /// </param>
            /// <returns>
            ///   The path to the file from which the assembly was loaded.
            /// </returns>
            public string GetPathOfAssembly(AssemblyName name)
            {
                throw new NotSupportedException();
            }

            /// <summary>
            ///   Loads a type with the specified name.
            /// </summary>
            /// <param name="name">
            ///   The name of the type. If the type name is not a fully qualified name that indicates an assembly,
            ///   this service will search its internal set of referenced assemblies.
            /// </param>
            /// <param name="throwOnError">
            ///   true if this method should throw an exception if the assembly cannot be located;
            ///   otherwise, false, and this method returns null if the assembly cannot be located.
            /// </param>
            /// <param name="ignoreCase">
            ///   true to ignore case when searching for types; otherwise, false.
            /// </param>
            /// <returns>
            ///   An instance of <see cref="T:System.Type"></see> that corresponds to the specified name,
            ///   or null if no type can be found.
            /// </returns>
            public Type GetType(string name, bool throwOnError, bool ignoreCase)
            {
                Type returnType;
                // 0, Search the type from the type cache pool.
                if (this._typeCachePool.TryGetValue(name, out returnType))
                {
                    return returnType;
                }

                // 1, Search the type use the Type.GetType method.
                returnType = Type.GetType(name, false, ignoreCase);
                if (returnType != null)
                {
                    this._typeCachePool.Add(name, returnType);
                    return returnType;
                }

                Dictionary<Assembly, string> componentAssemblysCache = new Dictionary<Assembly, string>();
                // 2, Search the type in root component's assembly.               
                if (this._designerLoaderHost.RootComponent != null)
                {
                    Assembly assembly = this._designerLoaderHost.RootComponent.GetType().Assembly;
                    componentAssemblysCache.Add(assembly, assembly.FullName);
                    returnType = this.GetType(assembly, name, false, ignoreCase);
                    if (returnType != null)
                    {
                        this._typeCachePool.Add(name, returnType);
                        return returnType;
                    }
                }
                else
                {
                    // Form is default root component                   
                    Assembly assembly = typeof(Form).Assembly;
                    componentAssemblysCache.Add(assembly, assembly.FullName);
                    returnType = this.GetType(assembly, name, false, ignoreCase);
                    if (returnType != null)
                    {
                        this._typeCachePool.Add(name, returnType);
                        return returnType;
                    }
                }

                // 3, Search the type in all components's assemblies which include in designer loader host's container.
                if (this._designerLoaderHost.Container != null)
                {
                    foreach (IComponent component in this._designerLoaderHost.Container.Components)
                    {
                        Assembly assembly = component.GetType().Assembly;
                        if (!componentAssemblysCache.ContainsKey(assembly))
                        {
                            componentAssemblysCache.Add(assembly, assembly.FullName);
                            returnType = this.GetType(assembly, name, false, ignoreCase);
                            if (returnType != null)
                            {
                                this._typeCachePool.Add(name, returnType);
                                return returnType;
                            }
                        }
                    }
                }

                // 4, Search the type in all components'a referenced assemblies.
                List<Assembly> componentAssemblys = new List<Assembly>(componentAssemblysCache.Keys);
                foreach (Assembly assembly in componentAssemblys)
                {
                    AssemblyName[] assemblyNames = assembly.GetReferencedAssemblies();
                    foreach (AssemblyName assemblyName in assemblyNames)
                    {
                        if (!componentAssemblysCache.ContainsValue(assemblyName.FullName))
                        {
                            Assembly newAssembly = Assembly.Load(assemblyName);
                            if (!componentAssemblysCache.ContainsKey(newAssembly))
                            {
                                componentAssemblysCache.Add(newAssembly, newAssembly.FullName);
                                returnType = this.GetType(newAssembly, name, false, ignoreCase);
                                if (returnType != null)
                                {
                                    this._typeCachePool.Add(name, returnType);
                                    return returnType;
                                }
                            }
                        }
                    }
                }

                // 5, Search the type in current domain's assemblies.
                Assembly[] assemblys = AppDomain.CurrentDomain.GetAssemblies();
                foreach (Assembly assembly in assemblys)
                {
                    if (!componentAssemblysCache.ContainsKey(assembly))
                    {
                        componentAssemblysCache.Add(assembly, assembly.FullName);
                        returnType = this.GetType(assembly, name, false, ignoreCase);
                        if (returnType != null)
                        {
                            this._typeCachePool.Add(name, returnType);
                            return returnType;
                        }
                    }
                }

                if (throwOnError)
                {
                    throw new ArgumentException();
                }

                return null;
            }

            /// <summary>
            ///   Loads a type with the specified name in a specified assembly.
            /// </summary>
            /// <param name="assembly">
            ///   The indicates assembly.
            /// </param>
            /// <param name="name">
            ///   The name of the type. If the type name is not a fully qualified name that indicates an assembly,
            ///   this service will search its internal set of referenced assemblies.
            /// </param>
            /// <param name="throwOnError">
            ///   true if this method should throw an exception if the assembly cannot be located;
            ///   otherwise, false, and this method returns null if the assembly cannot be located.
            /// </param>
            /// <param name="ignoreCase">
            ///   true to ignore case when searching for types; otherwise, false.
            /// </param>
            /// <returns>
            ///   An instance of <see cref="T:System.Type"></see> that corresponds to the specified name,
            ///   or null if no type can be found.
            /// </returns>
            private Type GetType(Assembly assembly, string name, bool throwOnError, bool ignoreCase)
            {
                System.Diagnostics.Debug.Assert(assembly != null);
                System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(name));

                Type returnType = assembly.GetType(name, false, ignoreCase);
                if (returnType == null)
                {
                    int length = name.IndexOf(",");
                    if (length != -1)
                    {
                        string shortName = name.Substring(0, length);
                        returnType = assembly.GetType(shortName, false, ignoreCase);
                    }
                }

                if (returnType != null)
                {
                    return returnType;
                }

                if (throwOnError)
                {
                    throw new ArgumentException();
                }

                return null;
            }

            /// <summary>
            ///   Loads a type with the specified name.
            /// </summary>
            /// <param name="name">
            ///   The name of the type. If the type name is not a fully qualified name that indicates an assembly,
            ///   this service will search its internal set of referenced assemblies.
            /// </param>
            /// <param name="throwOnError">
            ///   true if this method should throw an exception if the assembly cannot be located;
            ///   otherwise, false, and this method returns null if the assembly cannot be located.
            /// </param>
            /// <returns>
            ///   An instance of <see cref="T:System.Type"></see> that corresponds to the specified name,
            ///   or null if no type can be found.
            /// </returns>
            public Type GetType(string name, bool throwOnError)
            {
                return this.GetType(name, throwOnError, false);
            }

            /// <summary>
            ///   Loads a type with the specified name.
            /// </summary>
            /// <param name="name">
            ///   The name of the type. If the type name is not a fully qualified name that indicates an assembly,
            ///   this service will search its internal set of referenced assemblies.
            /// </param>
            /// <returns>
            ///   An instance of <see cref="T:System.Type"></see> that corresponds to the specified name,
            ///   or null if no type can be found.
            /// </returns>
            public Type GetType(string name)
            {
                return this.GetType(name, true);
            }

            /// <summary>
            ///   Adds a reference to the specified assembly.
            /// </summary>
            /// <param name="name">
            ///   An <see cref="T:System.Reflection.AssemblyName"></see> that indicates the assembly to reference.
            /// </param>
            public void ReferenceAssembly(System.Reflection.AssemblyName name)
            {
                throw new NotSupportedException();
            }

            #endregion
        }

        #endregion

        #region The DefaultTypeDescriptorFilterService class

        /// <summary>
        ///  Provides a TypeDescriptorFilterService to remove the InheritanceAttribute.
        /// </summary>
        private class DefaultTypeDescriptorFilterService : ITypeDescriptorFilterService
        {
            #region Instance Data

            /// <summary>
            ///   Save the old ITypeDescriptorFilterService.
            /// </summary>
            private ITypeDescriptorFilterService _oldService = null;

            /// <summary>
            ///   The root component will filter the InheritanceAttribute.
            /// </summary>
            private IComponent _rootComponent = null;

            #endregion

            #region Constructor

            /// <summary>
            ///   Initializes a new instance of the <see cref="DefaultTypeDescriptorFilterService"/> class.
            /// </summary>
            /// <param name="oldService">The old service.</param>
            /// <param name="rootComponent">The root component.</param>
            public DefaultTypeDescriptorFilterService(ITypeDescriptorFilterService oldService, IComponent rootComponent)
            {
                this._oldService = oldService;
                this._rootComponent = rootComponent;
            }

            #endregion

            #region ITypeDescriptorFilterService Members

            /// <summary>
            ///   Filters the attributes that a component exposes through a <see cref="T:System.ComponentModel.TypeDescriptor"/>.
            /// </summary>
            /// <param name="component">
            ///   The component to filter the attributes of.
            /// </param>
            /// <param name="attributes">
            ///   A dictionary of attributes that can be modified.
            /// </param>
            /// <returns>
            ///   true if the set of filtered attributes is to be cached; false if the filter service must query again.
            /// </returns>
            public bool FilterAttributes(IComponent component, IDictionary attributes)
            {
                bool result = true;

                if (this._oldService != null)
                {
                    result = this._oldService.FilterAttributes(component, attributes);
                }

                if (attributes != null)
                {
                    if (this._rootComponent == null || this._rootComponent == component)
                    {
                        attributes.Remove(InheritanceAttribute.Default.TypeId);
                    }
                }

                return result;
            }

            /// <summary>
            ///   Filters the events that a component exposes through a <see cref="T:System.ComponentModel.TypeDescriptor"/>.
            /// </summary>
            /// <param name="component">
            ///   The component to filter events for.
            /// </param>
            /// <param name="events">
            ///   A dictionary of events that can be modified.
            /// </param>
            /// <returns>
            ///   true if the set of filtered events is to be cached; false if the filter service must query again.
            /// </returns>
            public bool FilterEvents(IComponent component, IDictionary events)
            {
                if (this._oldService != null)
                {
                    return this._oldService.FilterEvents(component, events);
                }

                return true;
            }

            /// <summary>
            ///   Filters the properties that a component exposes through a <see cref="T:System.ComponentModel.TypeDescriptor"/>.
            /// </summary>
            /// <param name="component">
            ///   The component to filter properties for.
            /// </param>
            /// <param name="properties">
            ///   A dictionary of properties that can be modified.
            /// </param>
            /// <returns>
            ///   true if the set of filtered properties is to be cached; false if the filter service must query again.
            /// </returns>
            public bool FilterProperties(IComponent component, IDictionary properties)
            {
                if (this._oldService != null)
                {
                    return this._oldService.FilterProperties(component, properties);
                }

                return true;
            }

            #endregion
        }

        #endregion

        #endregion

        /// <summary>
        ///   Clones a new instance of <see cref="T:IComponent"/> from the source <see cref="T:IComponent"/>.
        /// </summary>
        /// <param name="component">
        ///   The source <see cref="T:IComponent"/> will be clone.
        /// </param>
        /// <returns>
        ///   A new instance of <see cref="T:IComponent"/>.
        /// </returns>
        public static IComponent CloneComponent(IComponent component)
        {
            if (component == null)
            {
                throw new ArgumentNullException();
            }

            //
            // Replace the old DescriptorFilterService with the new DefaultTypeDescriptorFilterService.
            // The new DefaultTypeDescriptorFilterService will filter the InheritanceAttribute.
            //
            IServiceContainer serviceContainer = null;
            ITypeDescriptorFilterService oldDescriptorFilterService = null;
            if (component.Site != null)
            {
                serviceContainer = (IServiceContainer)component.Site.GetService(typeof(IServiceContainer));
                if (serviceContainer != null)
                {
                    oldDescriptorFilterService = serviceContainer.GetService(typeof(ITypeDescriptorFilterService)) as ITypeDescriptorFilterService;
                    if (oldDescriptorFilterService != null)
                    {
                        serviceContainer.RemoveService(typeof(ITypeDescriptorFilterService));
                    }
                    serviceContainer.AddService(typeof(ITypeDescriptorFilterService), new DefaultTypeDescriptorFilterService(oldDescriptorFilterService, component));
                }
            }

            IComponent clonedComponent = CloneObject(component) as IComponent;

            //
            // Restore the DescriptorFilterService.
            //
            if (serviceContainer != null)
            {
                serviceContainer.RemoveService(typeof(ITypeDescriptorFilterService));
                if (oldDescriptorFilterService != null)
                {
                    serviceContainer.AddService(typeof(ITypeDescriptorFilterService), oldDescriptorFilterService);
                }
            }

            return clonedComponent;
        }

        /// <summary>
        ///   Loads a <see cref="T:IComponent"/> from the given stream.
        /// </summary>
        /// <param name="stream">
        ///   The stream from which to load the <see cref="T:IComponent"/>.
        /// </param>
        /// <returns>
        ///   The loaded <see cref="T:IComponent"/>.
        /// </returns>
        public static IComponent LoadComponent(Stream stream)
        {
            return LoadObject(stream) as IComponent;
        }

        /// <summary>
        ///   Saves the <see cref="T:IComponent"/> to the given stream.
        /// </summary>
        /// <param name="component">
        ///   The <see cref="T:IComponent"/> will be serialized to save.
        /// </param>
        /// <param name="stream">
        ///   The stream to which the <see cref="T:IComponent"/> will be serialized.
        /// </param>
        public static void SaveComponent(IComponent component, Stream stream)
        {
            if (component == null)
            {
                throw new ArgumentNullException();
            }

            //
            // Replace the old DescriptorFilterService with the new DefaultTypeDescriptorFilterService.
            // The new DefaultTypeDescriptorFilterService will filter the InheritanceAttribute.
            //
            IServiceContainer serviceContainer = null;
            ITypeDescriptorFilterService oldDescriptorFilterService = null;
            if (component.Site != null)
            {
                serviceContainer = (IServiceContainer)component.Site.GetService(typeof(IServiceContainer));
                if (serviceContainer != null)
                {
                    oldDescriptorFilterService = serviceContainer.GetService(typeof(ITypeDescriptorFilterService)) as ITypeDescriptorFilterService;
                    if (oldDescriptorFilterService != null)
                    {
                        serviceContainer.RemoveService(typeof(ITypeDescriptorFilterService));
                    }
                    serviceContainer.AddService(typeof(ITypeDescriptorFilterService), new DefaultTypeDescriptorFilterService(oldDescriptorFilterService, component));
                }
            }

            SaveObject(component, stream);

            //
            // Restore the DescriptorFilterService.
            //
            if (serviceContainer != null)
            {
                serviceContainer.RemoveService(typeof(ITypeDescriptorFilterService));
                if (oldDescriptorFilterService != null)
                {
                    serviceContainer.AddService(typeof(ITypeDescriptorFilterService), oldDescriptorFilterService);
                }
            }
        }

        /// <summary>
        ///   Clones a new instance of <see cref="T:Object"/> from the source <see cref="T:Object"/>.
        /// </summary>
        /// <param name="value">
        ///   The source <see cref="T:Object"/> will be clone.
        /// </param>
        /// <returns>
        ///   A new instance of <see cref="T:Object"/>.
        /// </returns>
        public static object CloneObject(object value)
        {
            using (DesignSurface designSurface = new DesignSurface())
            {
                designSurface.BeginLoad(new DefaultCodeDomDesignerLoader());
                ComponentSerializationService serializationService = designSurface.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;

                SerializationStore store = serializationService.CreateStore();
                serializationService.Serialize(store, value);
                store.Close();
                ICollection collection = serializationService.Deserialize(store);

                foreach (IComponent associatedComponent in designSurface.ComponentContainer.Components)
                {
                    designSurface.ComponentContainer.Remove(associatedComponent);
                }

                IEnumerator enumerator = collection.GetEnumerator();
                if (enumerator.MoveNext())
                {
                    return enumerator.Current;
                }

                return null;
            }
        }

        /// <summary>
        ///   Loads a <see cref="T:Object"/> from the given stream.
        /// </summary>
        /// <param name="stream">
        ///   The stream from which to load the <see cref="T:Object"/>.
        /// </param>
        /// <returns>
        ///   The loaded <see cref="T:Object"/>.
        /// </returns>
        public static object LoadObject(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException();
            }

            using (DesignSurface designSurface = new DesignSurface())
            {
                designSurface.BeginLoad(new DefaultCodeDomDesignerLoader());
                ComponentSerializationService serializationService = designSurface.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;

                stream.Position = 0;
                SerializationStore store = serializationService.LoadStore(stream);
                ICollection collection = serializationService.Deserialize(store);

                foreach (IComponent associatedComponent in designSurface.ComponentContainer.Components)
                {
                    designSurface.ComponentContainer.Remove(associatedComponent);
                }

                IEnumerator enumerator = collection.GetEnumerator();
                if (enumerator.MoveNext())
                {
                    return enumerator.Current;
                }

                return null;
            }
        }

        /// <summary>
        ///   Saves the <see cref="T:Object"/> to the given stream.
        /// </summary>
        /// <param name="value">
        ///   The <see cref="T:Object"/> will be serialized to save.
        /// </param>
        /// <param name="stream">
        ///   The stream to which the <see cref="T:Object"/> will be serialized.
        /// </param>
        public static void SaveObject(object value, Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException();
            }

            using (DesignSurface designSurface = new DesignSurface())
            {
                designSurface.BeginLoad(new DefaultCodeDomDesignerLoader());
                ComponentSerializationService serializationService = designSurface.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;

                SerializationStore store = serializationService.CreateStore();
                serializationService.Serialize(store, value);
                store.Save(stream);
            }
        }

        /// <summary>
        ///   Gets the source code of the <see cref="T:IComponent"/>.
        /// </summary>
        /// <param name="component">
        ///   The source <see cref="T:IComponent"/> will get code.
        /// </param>
        /// <returns>
        ///   A <b>string value indicates the source code.</b>
        /// </returns>
        public static string GetCode(IComponent component)
        {
            return GetCode(component, null);
        }

        /// <summary>
        ///   Gets the source code of the <see cref="T:IComponent"/>.
        /// </summary>
        /// <param name="component">
        ///   The source <see cref="T:IComponent"/> will get code.
        /// </param>
        /// <param name="codeDomProvider">
        ///   A <see cref="CodeDomProvider"/> indicates the code DOM provider.
        /// </param>
        /// <returns>
        ///   A <b>string value indicates the source code.</b>
        /// </returns>
        public static string GetCode(IComponent component, CodeDomProvider codeDomProvider)
        {
            if (component == null)
            {
                throw new ArgumentNullException();
            }

            using (DesignSurface designSurface = new DesignSurface())
            {
                DefaultCodeDomDesignerLoader loader = new DefaultCodeDomDesignerLoader();
                designSurface.BeginLoad(loader);
                ComponentSerializationService serializationService = designSurface.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;

                designSurface.ComponentContainer.Add(component);
                string code = loader.GenerateCode(codeDomProvider);
                designSurface.ComponentContainer.Remove(component);
                return code;
            }
        }
    }

    #endregion
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值