File: src\Microsoft.DotNet.Wpf\src\Shared\System\Windows\Markup\Replacements\TypeUriConverter.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\System.Xaml\System.Xaml.csproj (System.Xaml)
// 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.
 
#nullable disable
 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;
 
namespace System.Xaml.Replacements
{
    /// <summary>
    /// Limited converter for string <--> System.Uri
    /// </summary>
    internal class TypeUriConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            ArgumentNullException.ThrowIfNull(sourceType);
 
            return sourceType == typeof(string) || sourceType == typeof(Uri);
        }
 
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return
                destinationType == typeof(InstanceDescriptor) ||
                destinationType == typeof(string) ||
                destinationType == typeof(Uri);
        }
 
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (value is Uri uri)
            {
                UriKind uriKind = UriKind.RelativeOrAbsolute;
                if (uri.IsWellFormedOriginalString())
                {
                    uriKind = uri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative;
                }
 
                if (destinationType == typeof(InstanceDescriptor))
                {
                    ConstructorInfo constructor = typeof(Uri).GetConstructor(new Type[] { typeof(string), typeof(UriKind) });
                    return  new InstanceDescriptor(constructor, new object[] { uri.OriginalString, uriKind });
                }
                else if (destinationType == typeof(string))
                {
                    return uri.OriginalString;
                }
                else if (destinationType == typeof(Uri))
                {
                    return new Uri(uri.OriginalString, uriKind);
                }
            }
 
            return base.ConvertTo(context, culture, value, destinationType);
        }
 
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is string uriString)
            {
                if (Uri.IsWellFormedUriString(uriString, UriKind.Absolute))
                {
                    return new Uri(uriString, UriKind.Absolute);
                }
 
                if (Uri.IsWellFormedUriString(uriString, UriKind.Relative))
                {
                    return new Uri(uriString, UriKind.Relative);
                }
 
                return new Uri(uriString, UriKind.RelativeOrAbsolute);
            }
 
            if (value is Uri uri)
            {
                if (uri.IsWellFormedOriginalString())
                {
                    return new Uri(uri.OriginalString, uri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative);
                }
 
                return new Uri(uri.OriginalString, UriKind.RelativeOrAbsolute);
            }
 
            return base.ConvertFrom(context, culture, value);
        }
 
        public override bool IsValid(ITypeDescriptorContext context, object value)
        {
            if (value is string uriString)
            {
                return Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out _);
            }
 
            return value is Uri;
        }
    }
}