提问人:Alex Terkov 提问时间:11/27/2022 最后编辑:Alex Terkov 更新时间:11/27/2022 访问量:323
如何在运行时将字符串对象转换为通用对象?
How to convert string object to generic object at runtime?
问:
简化示例:
我有一个支持从字符串直接转换的类
public class MyClass {
public static explicit operator MyClass(string stringValue) => new MyClass();
public static MyClass Parse(string value) => new MyClass();
}
我可以在编译时将字符串转换为 MyClass,例如 (MyClass)“Some value”。但是当我在运行时从字符串转换为此类类型时,我从“System.String”到“SomeNamespace.MyClass”的强制转换无效。
我怎样才能解决这个问题?我需要在运行时从字符串转换为泛型类
我试过:
var result = Convert.ChangeType("Parsable string", typeof(MyClass));
var converter = TypeDescriptor.GetConverter(typeof(MyClass));
var result = converter.ConvertFromString("Parsable string");
但是在这两个中我都有一个错误:从“System.String”到“SomeNamespace.MyClass”的强制转换无效
所以我的问题是 String 类不知道如何将自身转换为 Unknown 类。但是我所有的 Unknown 类都知道如何从 String 投射到自己身上......like (UnknownClass)(“一些字符串值”)
关于用例:
这是运行时文本数据模型的分析器。在运行时,我有一个IList<string>它表示来自外部API的一些对象。我需要在运行时将此 IList 转换为我的域对象。我无法对具体的类实现进行硬编码(因为我只知道它在运行时是什么对象)。这是我的实现,一个泛型函数,它应该将 PropertyInfo(泛型对象)和 Strings(来自 API 的值)的字典转换为泛型对象。我想我需要一些DoDirectCast(Type type, string value),它将把值定向到类型以设置y泛型对象的参数
public T Transform<T>(Dictionary<PropertyInfo, string> arrOfPropOfT)
{
var returnObject = new T();
foreach (var keyValuePair in arrOfPropOfT)
{
Type propertyType = keyValuePair.value;
string castableValue = keyValuePair.key;
object? value = DoDirectCast(propertyType, castableValue);
propertyInfo.SetValue(returnObject, value)
}
return returnObject;
}
答:
要完成工作,您需要为类实现:TypeDescriptor.GetConverter
TypeConverter
[TypeConverter(typeof(MyClassConv))]
public class MyClass
{
public static explicit operator MyClass(string stringValue) => new MyClass();
public static MyClass Parse(string value) => new MyClass();
}
class MyClassConv : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return MyClass.Parse((string)value);
}
}
如果你想使用反射,你可以检查类型是否已经定义并调用它:op_Explicit
var propertyType = typeof(MyClass);
var method = t.GetMethod("op_Explicit", new[] { typeof(string) });
var result = method.Invoke(null, new object[] { "test" });
但总的来说,反射是一个非常繁重的工具,我建议你至少考虑为这个用例构建和编译表达式树。或者甚至更好地研究源生成器。
评论
下一个:投射到任何类型
评论