Domanda

Vorrei implementare la conversione tra due classi di libreria da Convert.ChangeType in C #. Non posso cambiare nessuno dei due tipi. Ad esempio la conversione tra Guid e byte [].

Guid g = new Guid();
object o1 = g;
byte[] b = (byte[]) Convert.ChangeType(o1, typeof(byte[])); // throws exception

Sono consapevole che Guid fornisce un metodo ToByteArray (), ma vorrei che fosse chiamato quando Guid viene convertito in byte []. Il motivo alla base di ciò è che la conversione avviene anche nel codice della libreria (AseDataAdapter) che non posso modificare. Quindi è possibile definire una regola di conversione tra due tipi senza modificare il codice sorgente di una delle due classi?

Stavo sperimentando TypeConverter, ma non sembra funzionare neanche:

Guid g = new Guid();
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Guid));
byte[] b2 = (byte[])tc.ConvertTo(g, typeof(byte[])); // throws exception

La variabile tc viene impostata su System.ComponentModel.GuidConverter che non supporta le conversioni in byte []. Posso avere due TypeConverter per la stessa classe? Anche se potessi, non dovrei anteporre un attributo al codice sorgente della classe per assegnare un TypeConverter?

Grazie

È stato utile?

Soluzione

Puoi cambiare il TypeConverter registrato per qualcosa usando TypeDescriptor.AddAttributes ; questo non è esattamente lo stesso di Convert.ChangeType , ma può bastare:

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);
    }
}

Altri suggerimenti

System.ComponentModel.ICustomTypeDescriptor

Sì, è possibile. Leggi la documentazione su MSDN per informazioni correlate per "iniettare" quella nel programma in esecuzione. (TypeDescriptor fornisce il metodo IIRC).

Se il codice che esegue la conversione supporta TypeConverter è possibile utilizzare TypeConverterAttribute a livello di assembly.

Purtroppo no, non puoi - potresti scrivere un metodo di estensione che apparire sia una conversione tra due tipi come parte del framework.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top