File: CustomConverter.cs
Web Access
Project: src\src\Common\tests\TestUtilities\System.Private.Windows.Core.TestUtilities.csproj (System.Private.Windows.Core.TestUtilities)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.ComponentModel;
 
namespace System;
 
public static class CustomConverter
{
    /// <summary>
    ///  Registers a TypeConverter with the specified type.
    /// </summary>
    public static RegistrationScope RegisterConverter(Type type, TypeConverter converter)
    {
        ArgumentNullException.ThrowIfNull(type);
        ArgumentNullException.ThrowIfNull(converter);
 
        TypeDescriptionProvider parentProvider = TypeDescriptor.GetProvider(type);
        CustomTypeDescriptionProvider newProvider = new(parentProvider, converter);
        TypeDescriptor.AddProvider(newProvider, type);
        return new RegistrationScope(type, newProvider);
    }
 
    /// <summary>
    ///  Manages the registration lifetime of a TypeConverter to a type.
    ///  This is meant to be utilized in a <see langword="using"/> statement to ensure
    ///  <see cref="TypeDescriptor.RemoveProvider(TypeDescriptionProvider, Type)"/> is called when going out of scope with the using.
    /// </summary>
    public readonly ref struct RegistrationScope
    {
        private readonly Type _type;
        private readonly TypeDescriptionProvider _provider;
 
        public RegistrationScope(Type type, TypeDescriptionProvider provider)
        {
            _type = type;
            _provider = provider;
        }
 
        public void Dispose() => TypeDescriptor.RemoveProvider(_provider, _type);
    }
 
    public class CustomTypeDescriptionProvider : TypeDescriptionProvider
    {
        private readonly TypeConverter _converter;
 
        public CustomTypeDescriptionProvider(TypeDescriptionProvider parent, TypeConverter converter) : base(parent)
            => _converter = converter;
 
        public override ICustomTypeDescriptor GetTypeDescriptor(
            [DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type objectType,
            object? instance) => new TypeConverterProvider(base.GetTypeDescriptor(objectType, instance), _converter);
 
        private sealed class TypeConverterProvider : CustomTypeDescriptor
        {
            private readonly TypeConverter _converter;
 
            public TypeConverterProvider(ICustomTypeDescriptor? parent, TypeConverter converter) : base(parent)
                => _converter = converter;
 
            public override TypeConverter GetConverter() => _converter;
        }
    }
}