C#中Converter的深度应用指南

一、基础类型转换器

1.1 内置类型转换

// 使用Convert类进行基础类型转换
int intValue = Convert.ToInt32("123");  // 字符串转整型
double dblValue = Convert.ToDouble("3.14");  // 字符串转双精度
DateTime dateValue = Convert.ToDateTime("2025-08-01");  // 字符串转日期
图片[1]_C#中Converter的深度应用指南_知途无界

1.2 安全转换方法

// 使用TryParse避免转换异常
if (int.TryParse("456", out int safeInt)) {
    Console.WriteLine($"安全转换结果: {safeInt}");
} else {
    Console.WriteLine("转换失败");
}

二、自定义类型转换器

2.1 IConvertible接口实现

public class Product : IConvertible
{
    public string Name { get; set; }
    public decimal Price { get; set; }

    public TypeCode GetTypeCode() => TypeCode.Object;

    public decimal ToDecimal(IFormatProvider provider) => Price;

    // 实现其他接口方法...
}

2.2 TypeConverter应用

[TypeConverter(typeof(ProductConverter))]
public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class ProductConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
        => sourceType == typeof(string);

    public override object ConvertFrom(ITypeDescriptorContext context, 
        CultureInfo culture, object value)
    {
        var parts = ((string)value).Split('|');
        return new Product { Id = parts[0], Name = parts[1] };
    }
}

// 使用示例
var converter = TypeDescriptor.GetConverter(typeof(Product));
var product = (Product)converter.ConvertFrom("P1001|笔记本电脑");

三、JSON序列化转换

3.1 JsonConverter应用

public class DecimalJsonConverter : JsonConverter<decimal>
{
    public override decimal Read(ref Utf8JsonReader reader, 
        Type typeToConvert, JsonSerializerOptions options)
        => reader.GetDecimal();

    public override void Write(Utf8JsonWriter writer, 
        decimal value, JsonSerializerOptions options)
        => writer.WriteStringValue(value.ToString("N2"));
}

// 注册使用
var options = new JsonSerializerOptions
{
    Converters = { new DecimalJsonConverter() }
};
string json = JsonSerializer.Serialize(new { Amount = 1234.5678m }, options);

3.2 复杂对象转换

public class ProductJsonConverter : JsonConverter<Product>
{
    public override Product Read(ref Utf8JsonReader reader, 
        Type typeToConvert, JsonSerializerOptions options)
    {
        using var jsonDoc = JsonDocument.ParseValue(ref reader);
        var root = jsonDoc.RootElement;
        return new Product {
            Id = root.GetProperty("product_code").GetString(),
            Name = root.GetProperty("product_name").GetString(),
            Price = root.GetProperty("price").GetDecimal()
        };
    }

    // Write方法实现...
}

四、LINQ查询转换

4.1 Select投影转换

var products = new List<Product>();
var productDtos = products.Select(p => new ProductDto
{
    Id = p.Id,
    DisplayName = $"{p.Name} (${p.Price})"
}).ToList();

4.2 自定义LINQ转换器

public static class LinqExtensions
{
    public static IEnumerable<TResult> ConvertAll<TSource, TResult>(
        this IEnumerable<TSource> source, 
        Func<TSource, TResult> converter)
    {
        foreach (var item in source)
        {
            yield return converter(item);
        }
    }
}

// 使用示例
var discountedProducts = products.ConvertAll(p => new {
    p.Name,
    DiscountPrice = p.Price * 0.9m
});

五、数据库映射转换

5.1 Dapper类型处理器

public class ProductStatusHandler : SqlMapper.TypeHandler<ProductStatus>
{
    public override ProductStatus Parse(object value)
        => ProductStatus.FromValue((int)value);

    public override void SetValue(IDbDataParameter parameter, ProductStatus value)
    {
        parameter.Value = value.Value;
        parameter.DbType = DbType.Int32;
    }
}

// 注册处理器
SqlMapper.AddTypeHandler(new ProductStatusHandler());

5.2 EF Core值转换器

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        .Property(p => p.Price)
        .HasConversion(
            v => v.ToString(),
            v => decimal.Parse(v));
}

六、ASP.NET Core模型绑定

6.1 自定义模型绑定器

public class ProductModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var model = new Product();
        model.Id = bindingContext.ValueProvider.GetValue("id").FirstValue;
        model.Name = bindingContext.ValueProvider.GetValue("name").FirstValue;
        bindingContext.Result = ModelBindingResult.Success(model);
        return Task.CompletedTask;
    }
}

// 注册绑定器
services.AddControllers(options =>
{
    options.ModelBinderProviders.Insert(0, new ProductModelBinderProvider());
});

6.2 格式化器转换

public class ProductInputFormatter : TextInputFormatter
{
    public ProductInputFormatter()
    {
        SupportedMediaTypes.Add("text/product");
        SupportedEncodings.Add(Encoding.UTF8);
    }

    public override async Task<InputFormatterResult> ReadRequestBodyAsync(
        InputFormatterContext context, Encoding encoding)
    {
        using var reader = new StreamReader(context.HttpContext.Request.Body, encoding);
        var content = await reader.ReadToEndAsync();
        var parts = content.Split(';');
        return InputFormatterResult.Success(new Product {
            Id = parts[0],
            Name = parts[1]
        });
    }
}

七、XAML绑定转换器

7.1 WPF值转换器

[ValueConversion(typeof(bool), typeof(Brush))]
public class BoolToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        return (bool)value ? Brushes.Green : Brushes.Red;
    }

    public object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

<!-- XAML中使用 -->
<Label Background="{Binding IsAvailable, Converter={StaticResource BoolToBrushConverter}}"/>

7.2 多值转换器

public class MultiValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, 
        object parameter, CultureInfo culture)
    {
        return $"{values[0]} - {values[1]}";
    }

    public object[] ConvertBack(object value, Type[] targetTypes, 
        object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

八、高级转换场景

8.1 表达式树转换

public static Expression<Func<TTarget, bool>> ConvertPredicate<TSource, TTarget>(
    Expression<Func<TSource, bool>> sourcePredicate)
{
    var parameter = Expression.Parameter(typeof(TTarget), "x");
    var body = new PredicateRewriter(parameter).Visit(sourcePredicate.Body);
    return Expression.Lambda<Func<TTarget, bool>>(body, parameter);
}

class PredicateRewriter : ExpressionVisitor
{
    private readonly ParameterExpression _parameter;

    public PredicateRewriter(ParameterExpression parameter)
    {
        _parameter = parameter;
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        // 实现属性映射逻辑
        return Expression.Property(_parameter, node.Member.Name);
    }
}

8.2 动态类型转换

public static dynamic ConvertToDynamic(object obj)
{
    var expando = new ExpandoObject();
    var dict = (IDictionary<string, object>)expando;
    foreach (var prop in obj.GetType().GetProperties())
    {
        dict[prop.Name] = prop.GetValue(obj);
    }
    return expando;
}

九、性能优化技巧

9.1 转换缓存策略

public static class ConverterCache<TInput, TOutput>
{
    private static readonly ConcurrentDictionary<TInput, TOutput> _cache 
        = new ConcurrentDictionary<TInput, TOutput>();

    public static TOutput Convert(TInput input, Func<TInput, TOutput> converter)
        => _cache.GetOrAdd(input, converter);
}

9.2 委托缓存

public static class Converter<TInput, TOutput>
{
    private static Func<TInput, TOutput> _converter;

    public static TOutput FastConvert(TInput input)
    {
        if (_converter == null)
        {
            var param = Expression.Parameter(typeof(TInput));
            var convertMethod = typeof(Convert).GetMethod("ChangeType", 
                new[] { typeof(object), typeof(Type) });
            var body = Expression.Convert(param, typeof(TOutput));
            _converter = Expression.Lambda<Func<TInput, TOutput>>(body, param).Compile();
        }
        return _converter(input);
    }
}

十、最佳实践总结

10.1 转换器选择矩阵

场景推荐方案性能考量
简单类型转换Convert类/TryParse最高效
复杂对象映射自定义TypeConverter中等,适合设计时
JSON/XML序列化JsonConverter需考虑序列化开销
数据库交互Dapper/EF Core转换器中等,批处理优化
UI数据绑定IValueConverter低频率触发

10.2 异常处理规范

public TOutput SafeConvert<TInput, TOutput>(TInput input)
{
    try
    {
        var converter = TypeDescriptor.GetConverter(typeof(TOutput));
        if (converter.CanConvertFrom(typeof(TInput)))
        {
            return (TOutput)converter.ConvertFrom(input);
        }
        throw new InvalidOperationException("不支持的转换类型");
    }
    catch (FormatException ex)
    {
        // 记录日志并返回默认值
        return default;
    }
    catch (NotSupportedException ex)
    {
        // 尝试其他转换方案
        return FallbackConvert(input);
    }
}

核心建议​:

  1. 优先使用框架内置转换机制(如System.Convert)
  2. 复杂场景采用TypeConverter实现设计时支持
  3. JSON序列化自定义需考虑跨平台兼容性
  4. 高频转换操作应使用表达式树或委托缓存
  5. 始终为转换操作添加适当的异常处理

性能关键点​:

  1. 避免在循环中重复创建转换器实例
  2. 对频繁使用的转换结果实施缓存
  3. 考虑使用Span处理内存密集型转换
  4. 异步IO操作时使用ValueTask减少分配
© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞50 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容