質問
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 つの TypeConverter を使用できますか?たとえそれができたとしても、TypeConverter を割り当てるためにクラスのソース コードの先頭に属性を追加する必要はないでしょうか?
ありがとう
解決
登録した内容を変更することができます 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);
}
}
他のヒント
System.ComponentModel.ICustomTypeDescriptor
はい、可能です。実行中のプログラムにそれを「挿入」するための関連情報については、MSDN のドキュメントを参照してください。(TypeDescriptor はメソッド IIRC を提供します)。
変換を実行しているコードがサポートしている場合 TypeConverter
使用できます TypeConverterAttribute
アセンブリレベルで。
残念ながら、それはできません。次のような拡張メソッドを作成できます。 現れる フレームワークの一部として 2 つのタイプ間の変換になります。