Inject tipo personalizado conversão para biblioteca de classes .NET
Pergunta
Eu gostaria de implementar a conversão entre duas classes de biblioteca por Convert.ChangeType em C #. Eu posso mudar nenhum dos dois tipos. Por exemplo a conversão entre GUID e byte [].
Guid g = new Guid();
object o1 = g;
byte[] b = (byte[]) Convert.ChangeType(o1, typeof(byte[])); // throws exception
Estou ciente de que Guid fornece um método ToByteArray (), mas eu gostaria de ter esse chamado quando Guid é convertida para byte []. A razão por trás disso é que a conversão também ocorre no código da biblioteca (AseDataAdapter) que eu não posso modificar. Assim, é possível definir uma regra de conversão entre dois tipos sem modificar o código fonte de qualquer das duas classes?
Eu estava experimentando com TypeConverter, mas não parece que quer trabalhar:
Guid g = new Guid();
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Guid));
byte[] b2 = (byte[])tc.ConvertTo(g, typeof(byte[])); // throws exception
O tc variável é configurado para System.ComponentModel.GuidConverter que não suporta conversões para byte []. Posso ter dois TypeConverters para a mesma classe? Mesmo que pudesse, não seria eu preciso para preceder um atributo ao código-fonte da classe para atribuir um TypeConverter?
Graças
Solução
Você pode alterar a TypeConverter
registrado para algo usando TypeDescriptor.AddAttributes
; isso não é exatamente o mesmo que Convert.ChangeType
, mas pode ser suficiente:
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);
}
}
Outras dicas
System.ComponentModel.ICustomTypeDescriptor
Sim, é possível. Leia a documentação no MSDN para obter informações relacionadas a 'injetar' que para o programa em execução. (TypeDescriptor fornece o método IIRC).
Se o código que está executando as TypeConverter
s suporta a conversão você pode usar TypeConverterAttribute
em um nível de montagem.
Infelizmente não você não pode -. Você poderia escrever um método de extensão que aparecer ser uma conversão entre dois tipos como parte do quadro