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

如何在C#中创建类似ViewBag的自定义动态对象?

Got it! 在C#里实现类似ViewBag的动态对象其实非常直观,核心就是利用DynamicObject基类来自定义动态行为。下面我给你完整的实现方案,包括两种访问方式的支持:

实现自定义ViewBag风格的动态对象

首先,我们需要创建一个继承自DynamicObject的类,它允许我们拦截动态属性的获取和设置操作,同时内部用一个字典来存储键值对(因为要支持任意属性名和object类型的值)。

完整代码实现

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

public class CustomViewBag : DynamicObject
{
    // 内部存储所有属性的字典
    private readonly Dictionary<string, object> _properties = new Dictionary<string, object>();

    // 支持 .PropertyName 方式赋值
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        // binder.Name 就是动态属性的名称
        _properties[binder.Name] = value;
        return true; // 表示赋值成功
    }

    // 支持 .PropertyName 方式取值
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        // 尝试从字典中获取对应属性的值
        return _properties.TryGetValue(binder.Name, out result);
    }

    // 支持 ["PropertyName"] 方式赋值
    public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
    {
        // 索引参数的第一个元素作为属性名(这里假设索引是字符串类型)
        if (indexes[0] is string propertyName)
        {
            _properties[propertyName] = value;
            return true;
        }
        return false;
    }

    // 支持 ["PropertyName"] 方式取值
    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {
        result = null;
        if (indexes[0] is string propertyName)
        {
            return _properties.TryGetValue(propertyName, out result);
        }
        return false;
    }

    // 可选:添加一个方法来获取所有属性,方便调试或遍历
    public IEnumerable<KeyValuePair<string, object>> GetAllProperties()
    {
        return _properties;
    }
}

如何使用这个动态对象

dynamic myViewBag = new CustomViewBag();

// 方式1:使用点语法赋值
myViewBag.Username = "JohnDoe";
myViewBag.Age = 30;
myViewBag.IsAdmin = true;

// 方式2:使用字典索引赋值
myViewBag["Email"] = "john@example.com";
myViewBag["Address"] = new { Street = "123 Main St", City = "NY" };

// 两种方式取值
Console.WriteLine(myViewBag.Username); // 输出 JohnDoe
Console.WriteLine(myViewBag["Email"]); // 输出 john@example.com

// 遍历所有属性
foreach (var prop in myViewBag.GetAllProperties())
{
    Console.WriteLine($"{prop.Key}: {prop.Value}");
}

关键细节说明

  • DynamicObject是.NET提供的基类,专门用于创建自定义动态类型,它通过重写虚方法来拦截动态操作。
  • 内部的Dictionary<string, object>负责存储所有动态属性的键值对,确保可以存储任意类型的值。
  • 重写TrySetMember/TryGetMember实现点语法访问,重写TrySetIndex/TryGetIndex实现字典式索引访问。
  • 如果需要支持更多动态操作(比如调用方法),可以继续重写DynamicObject的其他方法,比如TryInvokeMember。

额外注意事项

  • 动态类型在编译时不会做类型检查,所有解析都在运行时进行,所以要注意空引用异常(比如访问一个不存在的属性会返回null)。
  • 如果需要序列化这个对象(比如转JSON),默认的序列化器可能无法识别动态属性,这时可以把内部的_properties字典暴露为公共属性,或者实现ISerializable接口来支持序列化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:24:42