Injecter une conversion de type personnalisé dans les classes de la bibliothèque .NET

StackOverflow https://stackoverflow.com/questions/606854

  •  03-07-2019
  •  | 
  •  

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

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top