You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 00:48:05