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

C#.NET中如何将创建的简单匿名对象转换为自定义类类型

核心原因

你之前尝试的括号强转、as运算符转换失败是必然结果:C# 中的匿名类型是编译器自动生成的独立密封类,和你自定义的SomeClass不存在任何继承、类型兼容关系,而这两种转换方式仅支持存在兼容关系的类型转换,和语法熟练度无关。
你找到的逐字段映射方案失效,基本都是因为实现逻辑只匹配了公共属性(Property),没有覆盖公共字段(Field)——你给出的SomeClass定义里,两个成员都是公共字段,不是带get/set访问器的属性,自然无法被常规映射逻辑识别赋值。

可行解决方法
  • 手动映射(性能最优,推荐字段少的场景用)
    没有任何运行时开销,编译器会自动做类型检查,不会出现运行时匹配失败的问题:

    var test = new { FieldOne = "test2", FieldTwo = 2 };
    SomeClass casted = new SomeClass
    {
        FieldOne = test.FieldOne,
        FieldTwo = test.FieldTwo
    };
    

    如果后续把SomeClass的公共字段改成自动属性,写法还能更简洁。

  • 自定义通用映射方法(适配多场景)
    如果项目里有大量类似转换需求,可以自己写个泛型扩展方法,同时匹配源和目标的公共字段、公共属性,按名称和类型兼容规则赋值即可,参考实现:

    public static class TypeConvertExtension
    {
        public static T CastTo<T>(this object source) where T : new()
        {
            if (source == null) throw new ArgumentNullException(nameof(source));
            T instance = new T();
            Type sourceType = source.GetType();
            Type targetType = typeof(T);
            const BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
    
            // 匹配目标类公共字段
            foreach (var tField in targetType.GetFields(flag))
            {
                // 先找源对象的同名字段
                var sField = sourceType.GetField(tField.Name, flag);
                if (sField != null && tField.FieldType.IsAssignableFrom(sField.FieldType))
                {
                    tField.SetValue(instance, sField.GetValue(source));
                    continue;
                }
                // 再找源对象的同名属性
                var sProp = sourceType.GetProperty(tField.Name, flag);
                if (sProp != null && sProp.CanRead && tField.FieldType.IsAssignableFrom(sProp.PropertyType))
                {
                    tField.SetValue(instance, sProp.GetValue(source));
                }
            }
    
            // 匹配目标类公共属性
            foreach (var tProp in targetType.GetProperties(flag))
            {
                if (!tProp.CanWrite) continue;
                // 先找源对象的同名属性
                var sProp = sourceType.GetProperty(tProp.Name, flag);
                if (sProp != null && sProp.CanRead && tProp.PropertyType.IsAssignableFrom(sProp.PropertyType))
                {
                    tProp.SetValue(instance, sProp.GetValue(source));
                    continue;
                }
                // 再找源对象的同名字段
                var sField = sourceType.GetField(tProp.Name, flag);
                if (sField != null && tProp.PropertyType.IsAssignableFrom(sField.FieldType))
                {
                    tProp.SetValue(instance, sField.GetValue(source));
                }
            }
    
            return instance;
        }
    }
    

    调用方式非常简单:

    var test = new { FieldOne = "test2", FieldTwo = 2 };
    SomeClass casted = test.CastTo<SomeClass>();
    

    这个实现不管目标类用的是公共字段还是自动属性,只要成员名称、类型匹配就能正常赋值,不会出现你之前遇到的映射失效问题。

  • 序列化中转(代码最简洁,适合已有序列化库依赖的场景)
    如果项目里已经引入了JSON序列化库,可以先把匿名对象序列化为JSON,再反序列化为目标类型,不需要自己写映射逻辑,缺点是性能比前两种方案差,不适合高频调用的场景:

    // 以System.Text.Json为例
    var test = new { FieldOne = "test2", FieldTwo = 2 };
    SomeClass casted = JsonSerializer.Deserialize<SomeClass>(JsonSerializer.Serialize(test));
    
编码建议

日常编写C#业务类时,优先使用公共自动属性代替公共字段,符合.NET编码规范,绝大多数官方类库、第三方工具默认都是针对属性做适配,能避免很多类似这次的适配问题,调整后的类定义如下:

public class SomeClass
{
    public string FieldOne { get; set; }
    public int FieldTwo { get; set; }
}

内容的提问来源于stack exchange,提问作者Froschkoenig84

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:45:54