Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无法为泛型类型创建TypeConverter_C#_Visual Studio 2010_Asp.net Web Api_Asp.net 4.0_Typeconverter - Fatal编程技术网

C# 无法为泛型类型创建TypeConverter

C# 无法为泛型类型创建TypeConverter,c#,visual-studio-2010,asp.net-web-api,asp.net-4.0,typeconverter,C#,Visual Studio 2010,Asp.net Web Api,Asp.net 4.0,Typeconverter,我想为泛型类创建一个TypeConverter,如下所示: [TypeConverter(typeof(WrapperConverter<T>))] public class Wrapper<T> { public T Value { // get & set } // other methods } public class WrapperConverter<T> : TypeConverter&l

我想为泛型类创建一个
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);
   }
}
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
中,我遇到了最大的问题,因为我无法知道将输入字符串转换为哪个包装类

我已经创建了几个自定义类型和类型转换器,用于ASP.NET4WebAPI框架,这也是我需要使用它的地方

我尝试的另一件事是在运行时分配转换器的通用版本,如图所示,但WebAPI框架并不尊重它(这意味着,转换器从未创建过)


最后一点,我使用的是.NET 4.0和VS 2010。

我通过创建一个转换器来解决这个问题,该转换器可以处理从泛型类派生的所有类型。了解ConvertFrom中的泛型参数的大问题 通过在构造函数中捕获信息来解决此问题,如下所示

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");
    }
}
公共MyGenericConverter(类型)
{
如果(type.IsGenericType
&&type.GetGenericTypeDefinition()==typeof(MyGenericClass)
&&type.GetGenericArguments().Length==1)
{
_genericInstanceType=类型;
_innerType=type.GetGenericArguments()[0];
_innerTypeConverter=TypeDescriptor.GetConverter(_innerType);
}
其他的
{
抛出新ArgumentException(“不兼容类型”、“类型”);
}
}
我花了很长时间才发现.NET基础设施反射性地调用了此构造函数重载(如果已定义)。它不是文档化的TypeConverter类的一部分


希望这些都能帮助下一个人。

尽管@tcarvin的答案非常有趣-它在.NET Framework 4.6.1中对我有效,而且从我看来它也应该在.NET Core上有效,但有一种替代解决方案使用
TypeDescriptionProviderAttribute
,它不依赖于他描述的实现细节(构造函数接受类型为<代码>类型的参数)

具有:

public class FooTypeConverter<T> : TypeConverter { ... }

public class FooTypeDescriptor : CustomTypeDescriptor
{
    private Type objectType;

    public FooTypeDescriptor(Type objectType)
    {
        this.objectType = objectType;
    }

    public override TypeConverter GetConverter()
    {
        var genericArg = objectType.GenericTypeArguments[0];
        var converterType = typeof(FooTypeConverter<>).MakeGenericType(genericArg);
        return (TypeConverter)Activator.CreateInstance(converterType);
    }
}

public class FooTypeDescriptionProvider : TypeDescriptionProvider
{
    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return new FooTypeDescriptor(objectType);
    }
}
公共类FooTypeConverter:TypeConverter{…}
公共类FootTypeDescriptor:CustomTypeDescriptor
{
私有类型objectType;
公共FootTypeDescriptor(类型objectType)
{
this.objectType=objectType;
}
公共覆盖类型转换器GetConverter()
{
var genericArg=objectType.GenericTypeArguments[0];
var converterType=typeof(footypecoverter)。MakeGenericType(genericArg);
return(TypeConverter)Activator.CreateInstance(converterType);
}
}
公共类FooTypeDescriptionProvider:TypeDescriptionProvider
{
公共重写ICustomTypeDescriptor GetTypeDescriptor(类型objectType,对象实例)
{
返回新的FooTypeDescriptor(objectType);
}
}
您只需将TypeDescriptionProviderAttribute应用于目标类,如:

[TypeDescriptionProvider(typeof(FooTypeDescriptionProvider))]
public class Foo<T> { }
[TypeDescriptionProvider(typeof(FootTypeDescriptionProvider))]
公共类Foo{}
然后


TypeDescriptor.GetConverter(typeof(Foo))
将按预期工作。

我以前解决过这个问题,我相信我使用了dynamic来强制转换T,也使用了typeof。我应该能够在明天发布我的解决方案,因为我现在无法访问代码。这有帮助吗?@awright18谢谢,但我没有我需要的。我的问题主要是如何创建和关联a泛型类型的TypeConverter。很好!谢谢你的提示。解决了我的问题,我认为我无法确定目标类型。虽然可能没有记录,但将来可能会被破坏。嗯,我会看看。该项目仍处于4.0版本,所以我无法确认它是否只在该版本中工作。我猜给定的因为ASP.NET加载的
TypeConverter
可能与我尝试的WPF不同,所以答案对您很有用。WPF似乎在寻找一个无参数的构造函数。您能发布一个完整的类吗?
[TypeDescriptionProvider(typeof(FooTypeDescriptionProvider))]
public class Foo<T> { }