Injecter une conversion de type personnalisé dans les classes de la bibliothèque .NET
Question
Je voudrais implémenter la conversion entre deux classes de bibliothèque par Convert.ChangeType en C #. Je ne peux changer aucun des deux types. Par exemple, la conversion entre Guid et byte [].
Guid g = new Guid();
object o1 = g;
byte[] b = (byte[]) Convert.ChangeType(o1, typeof(byte[])); // throws exception
Je suis conscient du fait que Guid fournit une méthode ToByteArray (), mais j'aimerais que cette méthode soit appelée lorsque Guid est converti en octet []. La raison derrière cela est que la conversion a également lieu dans le code de bibliothèque (AseDataAdapter) que je ne peux pas modifier. Est-il donc possible de définir une règle de conversion entre deux types sans modifier le code source de l'une ou l'autre des classes?
J'essayais avec TypeConverter mais ne semble pas fonctionner non plus:
Guid g = new Guid();
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Guid));
byte[] b2 = (byte[])tc.ConvertTo(g, typeof(byte[])); // throws exception
La variable tc est définie sur System.ComponentModel.GuidConverter qui ne prend pas en charge les conversions en octet []. Puis-je avoir deux convertisseurs de type pour la même classe? Même si je le pouvais, n’aurais-je pas besoin d’ajouter un attribut au code source de la classe pour attribuer un TypeConverter?
Merci
La solution
Vous pouvez modifier le TypeConverter
enregistré en utilisant TypeDescriptor.AddAttributes
; ce n'est pas tout à fait la même chose que Convert.ChangeType
, mais cela peut suffire:
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);
}
}
Autres conseils
System.ComponentModel.ICustomTypeDescriptor
Oui, c'est possible. Lisez la documentation sur MSDN pour obtenir des informations connexes afin de "l'injecter" dans le programme en cours d'exécution. (TypeDescriptor fournit la méthode IIRC).
Si le code qui effectue la conversion prend en charge les TypeConverter
, vous pouvez utiliser TypeConverterAttribute
au niveau de l'ensemble.
Malheureusement, non, vous ne pouvez pas - vous pouvez écrire une méthode d'extension qui apparaîtrait comme une conversion entre deux types dans le cadre du cadre.