导读:本期聚焦于小伙伴创作的《C#中如何创建动态类型与动态对象,怎么合并两个对象并实现Map功能》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#中如何创建动态类型与动态对象,怎么合并两个对象并实现Map功能》有用,将其分享出去将是对创作者最好的鼓励。

C#中的动态类型允许开发者在编译阶段跳过类型检查,在运行时才解析类型相关的操作,这种特性非常适合处理结构不确定的对象场景。动态对象则可以通过继承特定基类实现属性的动态扩展,配合对象合并与Map功能,能大幅提升代码的灵活性。

C#中如何创建动态类型与动态对象,怎么合并两个对象并实现Map功能

C#动态类型与动态对象基础

动态类型的使用

C# 4.0引入了dynamic关键字,声明为dynamic的变量会在运行时进行类型解析,不需要提前定义具体的类型结构。我们可以通过以下示例创建简单的动态类型变量:

using System;

class Program
{
    static void Main()
    {
        // 声明动态类型变量
        dynamic dynamicVar = 10;
        Console.WriteLine(dynamicVar);
        
        // 动态修改变量类型
        dynamicVar = "hello dynamic";
        Console.WriteLine(dynamicVar);
        
        dynamicVar = new { Name = "test", Age = 20 };
        Console.WriteLine(dynamicVar.Name);
    }
}

创建自定义动态对象

如果要创建可以动态添加属性的对象,需要继承DynamicObject类,并重写相关方法。以下示例实现了一个支持动态添加属性的动态对象:

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Reflection;

public class CustomDynamicObject : DynamicObject
{
    // 存储动态属性的字典
    private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();

    // 获取动态属性值
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return _properties.TryGetValue(binder.Name, out result);
    }

    // 设置动态属性值
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _properties[binder.Name] = value;
        return true;
    }

    // 获取所有动态属性
    public Dictionary<string, object> GetAllProperties()
    {
        return new Dictionary<string, object>(_properties);
    }
}

合并两个动态对象

合并两个动态对象的核心思路是将两个对象的所有属性提取出来,合并到一个新的动态对象中,如果存在同名属性,可以根据需求选择覆盖或者保留原值。以下是完整的合并实现代码:

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Reflection;

public class ObjectMergeHelper
{
    // 合并两个动态对象,同名属性优先使用第二个对象的属性值
    public static CustomDynamicObject MergeDynamicObjects(CustomDynamicObject obj1, CustomDynamicObject obj2)
    {
        var mergedObj = new CustomDynamicObject();
        var obj1Properties = obj1.GetAllProperties();
        var obj2Properties = obj2.GetAllProperties();

        // 先添加第一个对象的所有属性
        foreach (var prop in obj1Properties)
        {
            ((dynamic)mergedObj).GetType().GetMethod("TrySetMember")?.Invoke(mergedObj, new object[] { new CustomBinder(prop.Key), prop.Value });
            // 使用反射调用TrySetMember更通用,也可以直接通过dynamic赋值
            dynamic dynamicMerged = mergedObj;
            dynamicMerged.GetType().GetProperty("Item")?.SetValue(dynamicMerged, prop.Value, new object[] { prop.Key });
        }

        // 再添加第二个对象的属性,覆盖同名属性
        foreach (var prop in obj2Properties)
        {
            dynamic dynamicMerged = mergedObj;
            dynamicMerged.GetType().GetProperty("Item")?.SetValue(dynamicMerged, prop.Value, new object[] { prop.Key });
        }

        return mergedObj;
    }

    // 简易绑定器,用于反射调用设置属性方法
    private class CustomBinder : GetMemberBinder
    {
        public CustomBinder(string name) : base(name, false) { }

        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            return errorSuggestion;
        }
    }
}

// 测试合并功能
class TestMerge
{
    static void Main()
    {
        dynamic obj1 = new CustomDynamicObject();
        obj1.Name = "张三";
        obj1.Age = 25;

        dynamic obj2 = new CustomDynamicObject();
        obj2.Age = 30;
        obj2.Address = "北京";

        var merged = ObjectMergeHelper.MergeDynamicObjects(obj1, obj2);
        dynamic mergedDynamic = merged;
        Console.WriteLine($"姓名:{mergedDynamic.Name},年龄:{mergedDynamic.Age},地址:{mergedDynamic.Address}");
        // 输出结果:姓名:张三,年龄:30,地址:北京
    }
}

实现Map功能示例

Map功能通常指将一个对象的属性按照指定规则映射到另一个对象中,以下实现了一个通用的Map方法,支持将源对象的属性映射到目标对象:

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Reflection;

public class MapHelper
{
    // 将源对象的属性映射到目标动态对象
    public static CustomDynamicObject MapToDynamic(object source, Dictionary<string, string> propertyMapping = null)
    {
        var target = new CustomDynamicObject();
        var sourceType = source.GetType();
        var sourceProperties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (var sourceProp in sourceProperties)
        {
            // 如果有映射规则,使用映射后的属性名,否则使用原属性名
            string targetPropName = propertyMapping != null && propertyMapping.ContainsKey(sourceProp.Name) 
                ? propertyMapping[sourceProp.Name] 
                : sourceProp.Name;

            var value = sourceProp.GetValue(source);
            dynamic dynamicTarget = target;
            // 设置目标对象的动态属性
            dynamicTarget.GetType().GetProperty("Item")?.SetValue(dynamicTarget, value, new object[] { targetPropName });
        }

        return target;
    }

    // 将动态对象映射到有固定类型的目标对象
    public static T MapToObject<T>(CustomDynamicObject source) where T : new()
    {
        var target = new T();
        var targetProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        var sourceProperties = source.GetAllProperties();

        foreach (var targetProp in targetProperties)
        {
            if (sourceProperties.ContainsKey(targetProp.Name) && targetProp.CanWrite)
            {
                var value = sourceProperties[targetProp.Name];
                // 处理类型转换
                if (value != null && targetProp.PropertyType.IsAssignableFrom(value.GetType()))
                {
                    targetProp.SetValue(target, value);
                }
            }
        }

        return target;
    }
}

// 测试Map功能
class TestMap
{
    static void Main()
    {
        // 源对象
        var sourceObj = new { UserName = "李四", UserAge = 28, UserEmail = "test@ipipp.com" };
        
        // 属性映射规则:源属性名 -> 目标属性名
        var mapping = new Dictionary<string, string>
        {
            { "UserName", "Name" },
            { "UserAge", "Age" }
        };

        // 映射到动态对象
        var dynamicResult = MapHelper.MapToDynamic(sourceObj, mapping);
        dynamic dynamicResultDynamic = dynamicResult;
        Console.WriteLine($"Name:{dynamicResultDynamic.Name},Age:{dynamicResultDynamic.Age},Email:{dynamicResultDynamic.UserEmail}");

        // 定义目标固定类型
        public class UserInfo
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }

        // 动态对象映射到固定类型对象
        var userInfo = MapHelper.MapToObject<UserInfo>(dynamicResult);
        Console.WriteLine($"Name:{userInfo.Name},Age:{userInfo.Age}");
    }
}

注意事项

使用动态类型时需要注意,动态类型的操作在编译阶段不会进行类型检查,如果调用了不存在的属性或方法,会在运行时抛出RuntimeBinderException,因此建议在使用动态对象前做好属性存在性的校验。另外,动态对象的性能比静态类型略低,如果不是必要场景,不建议过度使用动态类型。

合并对象时如果属性类型不一致,需要做额外的类型转换处理,否则可能会出现赋值异常。Map功能的实现可以根据实际需求扩展,比如支持更多类型的转换、支持嵌套对象的映射等。

C#dynamic动态对象对象合并Map实现修改时间:2026-06-04 15:12:15

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。