27

C# で Convert.ChangeType による 2 つのライブラリ クラス間の変換を実装したいと考えています。どちらのタイプも変更できません。たとえば、Guid と byte[] の間の変換。

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

Guid が ToByteArray() メソッドを提供していることは承知していますが、Guid が byte[] に変換されたときに呼び出されるようにしたいと考えています。これの背後にある理由は、変更できないライブラリ コード (AseDataAdapter) でも変換が行われるためです。では、2 つのクラスのどちらのソースコードも変更せずに、2 つの型の間の変換規則を定義することは可能でしょうか?

私は TypeConverter を試していましたが、どちらもうまくいかないようです:

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

変数 tc は、byte[] への変換をサポートしない System.ComponentModel.GuidConverter に設定されます。同じクラスに 2 つの TypeConverters を使用できますか? できたとしても、TypeConverter を割り当てるために、クラスのソース コードの先頭に属性を追加する必要はありませんか?

ありがとう

4

4 に答える 4

51

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);
    }
}
于 2009-03-03T16:03:26.983 に答える
0

変換を実行しているコードがTypeConverters をサポートしている場合TypeConverterAttributeは、アセンブリ レベルで使用できます。

于 2009-03-03T15:43:31.443 に答える
-1
System.ComponentModel.ICustomTypeDescriptor

はい、可能です。実行中のプログラムに「注入」する関連情報については、MSDN のドキュメントを参照してください。(TypeDescriptor はメソッド IIRC を提供します)。

于 2009-03-03T15:59:09.333 に答える
-2

残念ながらできません。フレームワークの一部として、2 つの型の間の変換のように見える拡張メソッドを作成することはできます。

于 2009-03-03T15:36:29.590 に答える