多DTO共用TypeConverter时如何在ConvertFrom中获取目标转换类型
解决方案
目标类型获取方法
直接通过ITypeDescriptorContext实例的PropertyDescriptor.PropertyType属性即可获取需要转换的目标DTO类型,这是类型转换器标准上下文提供的元数据,适用于ASP.NET Core模型绑定、控件属性转换等绝大多数常规场景。
完整通用转换器实现
下面是调整后的可复用转换器代码,额外补充了属性类型自动转换逻辑,解决string转int、DateTime等非字符串属性的报错问题:
using System.ComponentModel; using System.Globalization; using System.Reflection; public class GenericDtoTypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { // 核心逻辑:获取目标转换类型 Type targetDtoType = context.PropertyDescriptor.PropertyType; var strVal = value as string; if (string.IsNullOrWhiteSpace(strVal)) { return Activator.CreateInstance(targetDtoType); } // 初始化目标类型实例 object dtoInstance = Activator.CreateInstance(targetDtoType); string[] filterPairs = strVal.Split(';', StringSplitOptions.RemoveEmptyEntries); foreach (var pair in filterPairs) { var keyValue = pair.Split(':', StringSplitOptions.RemoveEmptyEntries); if (keyValue.Length != 2) continue; string propertyName = keyValue[0].Trim(); string propertyValue = keyValue[1].Trim(); SetPropertyValue(dtoInstance, propertyName, propertyValue, culture); } return dtoInstance; } private void SetPropertyValue(object instance, string propertyName, string value, CultureInfo culture) { Type type = instance.GetType(); PropertyInfo property = type.GetProperties(BindingFlags.Instance | BindingFlags.Public) .FirstOrDefault(p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase) && p.CanWrite); if (property == null) return; // 自动转换字符串到属性对应的类型 object convertedValue = Convert.ChangeType(value, property.PropertyType, culture); property.SetValue(instance, convertedValue); } }
使用方法
在所有需要用到该转换器的DTO类上添加TypeConverter特性即可:
[TypeConverter(typeof(GenericDtoTypeConverter))] public class EmployeeFilter { // 你的属性定义 public int Id { get; set; } public string Name { get; set; } public DateTime? CreateTime { get; set; } } [TypeConverter(typeof(GenericDtoTypeConverter))] public class DepartmentFilter { // 其他DTO的属性定义 }
无Context场景兼容方案
如果你需要在没有传入ITypeDescriptorContext的场景下调用转换器,可以改用泛型实现的转换器,无需依赖上下文获取类型:
public class GenericDtoTypeConverter<TDto> : TypeConverter where TDto : new() { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var strVal = value as string; if (string.IsNullOrWhiteSpace(strVal)) { return new TDto(); } TDto dtoInstance = new TDto(); // 后续解析属性逻辑和上面的实现完全一致 // ... } }
使用时指定对应DTO的泛型参数即可:
[TypeConverter(typeof(GenericDtoTypeConverter<EmployeeFilter>))] public class EmployeeFilter { // 属性定义 }
内容的提问来源于stack exchange,提问作者Andes Lam
相关产品推荐
相关产品推荐

