File: System\Windows\Documents\Serialization\SerializerProvider.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#if !DONOTREFPRINTINGASMMETA
//
//
// Description: Manages plug-in document serializers
//
//              See spec at <Need to post existing spec>
//
 
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Xps.Serialization;
using Microsoft.Win32;
 
#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
namespace System.Windows.Documents.Serialization
{
    /// <summary>
    /// SerializerProvider enumerates plug-in serializers
    /// </summary>
    public sealed class SerializerProvider
    {
        #region Constructors
 
        /// <summary>
        /// creates a SerializerProvider
        /// The constructor accesses the registry to find all installed plug-ins
        /// </summary>
        /// <remarks>
        ///     Create a SerializerProvider listing all installed serializers (from the registry)
        ///
        ///     This method currently requires full trust to run.
        /// </remarks>
        public SerializerProvider()
        {
 
            SerializerDescriptor sd = null;
 
            List<SerializerDescriptor>  installedSerializers = new List<SerializerDescriptor>();
 
            sd = CreateSystemSerializerDescriptor();
 
            if (sd != null)
            {
                installedSerializers.Add(sd);
            }
 
            RegistryKey plugIns = _rootKey.CreateSubKey(_registryPath);
 
            if ( plugIns != null )
            {
                foreach ( string keyName in plugIns.GetSubKeyNames())
                {
                    sd = SerializerDescriptor.CreateFromRegistry(plugIns, keyName);
                    if (sd != null)
                    {
                        installedSerializers.Add(sd);
                    }
                }
 
                plugIns.Close();
            }
 
            _installedSerializers = installedSerializers.AsReadOnly();
        }
 
        #endregion
 
        #region Public Methods
 
        /// <summary>
        /// Registers the serializer plug-in identified by serializerDescriptor in the registry
        /// </summary>
        public static void RegisterSerializer(SerializerDescriptor serializerDescriptor, bool overwrite)
        {
 
            ArgumentNullException.ThrowIfNull(serializerDescriptor);
 
            RegistryKey plugIns = _rootKey.CreateSubKey(_registryPath);
            string serializerKey = $"{serializerDescriptor.DisplayName}/{serializerDescriptor.AssemblyName}/{serializerDescriptor.AssemblyVersion}/{serializerDescriptor.WinFXVersion}";
 
            if (!overwrite && plugIns.OpenSubKey(serializerKey) != null)
            {
                throw new ArgumentException(SR.SerializerProviderAlreadyRegistered, serializerKey);
            }
 
            RegistryKey newPlugIn = plugIns.CreateSubKey(serializerKey);
            serializerDescriptor.WriteToRegistryKey(newPlugIn);
            newPlugIn.Close();
        }
 
        /// <summary>
        /// Un-Registers the serializer plug-in identified by serializerDescriptor in the registry
        /// </summary>
        /// <remarks>
        ///     Removes a previously installed plug-n serialiazer from the registry
        ///
        ///     This method currently requires full trust to run.
        /// </remarks>
        public static void UnregisterSerializer(SerializerDescriptor serializerDescriptor)
        {
 
            ArgumentNullException.ThrowIfNull(serializerDescriptor);
 
            RegistryKey plugIns = _rootKey.CreateSubKey(_registryPath);
            string serializerKey = $"{serializerDescriptor.DisplayName}/{serializerDescriptor.AssemblyName}/{serializerDescriptor.AssemblyVersion}/{serializerDescriptor.WinFXVersion}";
 
            if (plugIns.OpenSubKey(serializerKey) == null)
            {
                throw new ArgumentException(SR.SerializerProviderNotRegistered, serializerKey);
            }
 
            plugIns.DeleteSubKeyTree(serializerKey);
        }
 
        /// <summary>
        /// Create a SerializerWriter identified by the passed in SerializerDescriptor on the passed in stream
        /// </summary>
        /// <remarks>
        ///     With a SerializerProvider (which requires full trust to ctor) and a SerializerDescriptor (which requires
        ///     full trust to obtain) create a SerializerWriter
        ///
        ///     This method currently requires full trust to run.
        /// </remarks>
        public SerializerWriter CreateSerializerWriter(SerializerDescriptor serializerDescriptor, Stream stream)
        {
 
            SerializerWriter serializerWriter = null;
 
            ArgumentNullException.ThrowIfNull(serializerDescriptor);
 
            string serializerKey = $"{serializerDescriptor.DisplayName}/{serializerDescriptor.AssemblyName}/{serializerDescriptor.AssemblyVersion}/{serializerDescriptor.WinFXVersion}";
 
            if (!serializerDescriptor.IsLoadable)
            {
                throw new ArgumentException(SR.SerializerProviderWrongVersion, serializerKey);
            }
            ArgumentNullException.ThrowIfNull(stream);
 
            bool found = false;
            foreach (SerializerDescriptor sd in InstalledSerializers)
            {
                if (sd.Equals(serializerDescriptor))
                {
                    found = true;
                    break;
                }
            }
 
            if (!found)
            {
                throw new ArgumentException(SR.SerializerProviderUnknownSerializer, serializerKey);
            }
 
            try
            {
                ISerializerFactory factory = serializerDescriptor.CreateSerializerFactory();
 
                serializerWriter = factory.CreateSerializerWriter(stream);
            }
            catch (FileNotFoundException)
            {
                throw new ArgumentException(SR.SerializerProviderCannotLoad, serializerDescriptor.DisplayName);
            }
            catch (FileLoadException)
            {
                throw new ArgumentException(SR.SerializerProviderCannotLoad, serializerDescriptor.DisplayName);
            }
            catch (BadImageFormatException)
            {
                throw new ArgumentException(SR.SerializerProviderCannotLoad, serializerDescriptor.DisplayName);
            }
            catch (MissingMethodException)
            {
                throw new ArgumentException(SR.SerializerProviderCannotLoad, serializerDescriptor.DisplayName);
            }
 
            return serializerWriter;
        }
 
        #endregion
 
        #region Private Methods
 
        /// <summary>
        /// Uses reflection to create the XpsSerializer
        /// </summary>
        /// <remarks>
        ///     Creates the Xps default serializer
        /// </remarks>
        /// <returns>SerializerDescriptor for new serializer</returns>
        private SerializerDescriptor CreateSystemSerializerDescriptor()
        {
 
            SerializerDescriptor serializerDescriptor = null;
 
            // The XpsSerializer (our default document serializer) is defined in ReachFramework.dll
            // But callers can only get here if the above demand succeeds, so they are already fully trusted
            serializerDescriptor = SerializerDescriptor.CreateFromFactoryInstance(
                                        new XpsSerializerFactory()
                                        );
 
            return serializerDescriptor;
        }
 
        #endregion
 
        #region Public Properties
 
        /// <summary>
        /// Returns collection of installed serializers
        /// </summary>
        public ReadOnlyCollection<SerializerDescriptor> InstalledSerializers
        {
            get
            {
                return _installedSerializers;
            }
        }
 
        #endregion
 
        #region Data
 
        private const string _registryPath =            @"SOFTWARE\Microsoft\WinFX Serializers";
        private static readonly RegistryKey _rootKey =  Registry.LocalMachine;
 
        private ReadOnlyCollection<SerializerDescriptor> _installedSerializers;
 
        #endregion
    }
}
#endif