19

TypeConverter次のように、ジェネリック クラスのを作成したいと思います。

[TypeConverter(typeof(WrapperConverter<T>))]
public class Wrapper<T> 
{

   public T Value 
   {
      // get & set 
   }

   // other methods

}


public class WrapperConverter<T> : TypeConverter<T>
{

   // only support To and From strings
   public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
   {
      if (sourceType == typeof(string))
      {
         return true;
      }
      return base.CanConvertFrom(context, sourceType);
   }

   public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
   {
      if (destinationType == typeof(string))
      {
         return true;
      }
      return base.CanConvertTo(context, destinationType);
   }

   public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
   {
      if (value is string)           
      {
         TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
         T inner = converter.ConvertTo(value, destinationType);
         return new Wrapper<T>(inner);
      }
      return base.ConvertFrom(context, culture, value);
   }

   public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
   {
      if (destinationType == typeof(System.String))
      {
         Wrapper<T> wrapper = value as Wrapper<T>();
         TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
         return converter.ConvertTo(wrapper.Value, destinationType);
      }   
      return base.ConvertTo(context, culture, value, destinationType);
   }
}

問題は、この行にジェネリックを含めることができないということです。許可されていません。

[TypeConverter(typeof(WrapperConverter<T>))]
public class Wrapper<T> 

Wrapper<T>私の次のアプローチは、任意のインスタンスを処理できる単一の非ジェネリック Converter を定義することでした。リフレクションとジェネリックの両方が混在しているため、メソッドとメソッドの両方を実装する方法に困惑しています。ConvertToConvertFrom

たとえば、私の ConvertTo は次のようになります。

public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
   if (destinationType == typeof(System.String)           
       && value.GetType().IsGenericType)
   {

       // 1.  How do I enforce that value is a Wrapper<T> instance?

       Type innerType = value.GetType().GetGenericArguments()[0];

       TypeConverter converter = TypeDescriptor.GetConverter(innerType);

       // 2.  How do I get to the T Value property?  Introduce an interface that Wrapper<T> implements maybe?
       object innerValue = ??? 

       return converter.ConvertTo(innerValue, destinationType);


   }
   return base.ConvertTo(context, culture, value, destinationType);
}

ConvertFrom着信文字列をどの Wrapper クラスに変換するかを知る方法がないため、最大の問題があります。

ASP.NET 4 Web API フレームワークで使用するカスタム型と TypeConverters をいくつか作成しましたが、ここでもこれを使用する必要があります。

私が試みたもう 1 つのことは、実行時にコンバーターのジェネリック バージョンを割り当てることでした。

最後に、私は .NET 4.0 と VS 2010 を使用しています。

4

2 に答える 2

43

ジェネリック クラスから派生したすべての型を処理できる単一の Converter を作成することで、これを解決しました。ConvertFrom 内のジェネリック引数 T を知るという大きな問題は、以下に示すようにコンストラクターで情報を取得することで解決されました。

public MyGenericConverter(Type type)
{
    if (type.IsGenericType 
        && type.GetGenericTypeDefinition() == typeof(MyGenericClass<>)
        && type.GetGenericArguments().Length == 1)
    {
        _genericInstanceType = type;
        _innerType = type.GetGenericArguments()[0];
        _innerTypeConverter = TypeDescriptor.GetConverter(_innerType);            
    }
    else
    {
        throw new ArgumentException("Incompatible type", "type");
    }
}

このコンストラクターのオーバーロードが定義されている場合、.NET インフラストラクチャーがこのコンストラクターのオーバーロードを反射的に呼び出すことを発見するのに、私は何年もかかりました。ドキュメント化された TypeConverter クラスの一部ではありませんでした。

これがすべて次の人に役立つことを願っています。

于 2013-02-20T13:16:27.470 に答える