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> { }