Внедрить пользовательское преобразование типов в классы библиотеки .NET.
Вопрос
Я хотел бы реализовать преобразование между двумя библиотечными классами с помощью Convert.ChangeType в С#.Я не могу изменить ни один из двух типов.Например, преобразование между Guid и byte[].
Guid g = new Guid();
object o1 = g;
byte[] b = (byte[]) Convert.ChangeType(o1, typeof(byte[])); // throws exception
Я знаю, что Guid предоставляет метод ToByteArray(), но я бы хотел, чтобы он вызывался, когда Guid преобразуется в byte[].Причина этого в том, что преобразование также происходит в коде библиотеки (AseDataAdapter), который я не могу изменить.Итак, можно ли определить правило преобразования между двумя типами, не изменяя исходный код любого из двух классов?
Я экспериментировал с TypeConverter, но, похоже, тоже не работает:
Guid g = new Guid();
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Guid));
byte[] b2 = (byte[])tc.ConvertTo(g, typeof(byte[])); // throws exception
Переменной tc присваивается значение System.ComponentModel.GuidConverter, которая не поддерживает преобразования в byte[].Могу ли я иметь два преобразователя типов для одного и того же класса?Даже если бы я мог, разве мне не пришлось бы добавлять атрибут к исходному коду класса, чтобы назначить TypeConverter?
Спасибо
Решение
Вы можете изменить зарегистрированный TypeConverter
для чего-то используя TypeDescriptor.AddAttributes
;это не совсем то же самое, что Convert.ChangeType
, но этого может быть достаточно:
using System;
using System.ComponentModel;
static class Program
{
static void Main()
{
TypeDescriptor.AddAttributes(typeof(Guid), new TypeConverterAttribute(
typeof(MyGuidConverter)));
Guid guid = Guid.NewGuid();
TypeConverter conv = TypeDescriptor.GetConverter(guid);
byte[] data = (byte[])conv.ConvertTo(guid, typeof(byte[]));
Guid newGuid = (Guid)conv.ConvertFrom(data);
}
}
class MyGuidConverter : GuidConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(byte[]) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(byte[]) || base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value != null && value is byte[])
{
return new Guid((byte[])value);
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(byte[]))
{
return ((Guid)value).ToByteArray();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
Другие советы
System.ComponentModel.ICustomTypeDescriptor
Да, это возможно.Прочтите документацию на MSDN для получения соответствующей информации, чтобы «внедрить» ее в работающую программу.(TypeDescriptor предоставляет метод IIRC).
Если код, выполняющий преобразование, поддерживает TypeConverter
ты можешь использовать TypeConverterAttribute
на уровне сборки.
К сожалению, нет, вы не можете - вы могли бы написать метод расширения, который бы появляться быть преобразованием между двумя типами как частью платформы.