2009-03-03 3 views
21

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

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

私は、GUIDがToByteArray()メソッドを提供することを承知していますが、私は、GUIDは、[]のバイトに変換されたときに呼び出されることがしたいです。これの背後にあるのは、私が変更できないライブラリコード(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は[]のバイトに変換をサポートしていないSystem.ComponentModel.GuidConverterに設定されます。同じクラスの2つのTypeConverterを持つことはできますか?たとえできても、TypeConverterを割り当てるためにクラスのソースコードに属性を付加する必要はありませんか?

おかげ

答えて

36

登録した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); 
    } 
} 
+1

素敵な例をありがとう:) – leppie

+0

+1 TypeDescriptor.AddAttributes経由で属性を追加することもできませんでした。これは非常に便利です。 –

+5

これらは実際の属性ではないことに注意してください。反射はそれらを見ません。 System.ComponentModelのみ –

-2

残念ながら、あなたがすることはできません - あなたはは、フレームワークの一部として、2種類の間の変換であるように思われる拡張メソッドを書くことができませんでした。

0

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

+0

私の知る限り、TypeConverterAttributeのないアセンブリレベルの使用はありません。型ごとおよびプロパティごとに行うことができ、TypeDescriptor経由でオーバーライドできますが、アセンブリレベルはありません。私は何かを逃したか? –

+0

TypeConverterAttributeはAttributeTargets.All ...とISTRで宣言され、WFで使用されています。 – Richard

0
System.ComponentModel.ICustomTypeDescriptor 

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

+0

それは大規模な過剰です...個々のプロパティ(PropertyDescriptorが尊重)で[TypeConverter]を使用するか、私の投稿に示されているグローバルなアプローチを使用してください。 –