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

C#如何为属性未知的动态对象定义接口?代码报错处理

问题描述

我编写了以下C#代码片段:

var databricksResponse = await _databricksLakehouseLogic.GetDatabricksDataBySQL(instanceId, query);
List<dynamic> records = new List<dynamic>();

if (databricksResponse?.Result != null)
{
    var arrayData = databricksResponse.Result[DataArray].ToList();

    List<ColumnSchema> columnsList = databricksResponse.Manifest.Schema.Columns.ToList();

    for (int i = 0; i < arrayData.Count; i++)
    {
        dynamic record = new System.Dynamic.ExpandoObject();

        for (int j = 0; j < columnsList.Count; j++)
        {
            var row = arrayData[i].ToList();
            var column = columnsList[j];
            //var value = arrayData[i][j];
            record[column.Name] = row[j];
        }

        records.Add(record);
    }
}

return await Task.FromResult(records);

执行record[column.Name] = row[j]时出现错误:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot apply indexing with [] to an expression of type'

请问如何为根据请求动态生成键的对象创建接口?

补充:后续了解到若提前未知列名,可使用Dictionary处理该场景。

解决方案

方法1:直接使用Dictionary<string, object>替代ExpandoObject

这是最直接的方案,完全规避动态类型的绑定问题,符合你补充提到的思路:

var databricksResponse = await _databricksLakehouseLogic.GetDatabricksDataBySQL(instanceId, query);
List<Dictionary<string, object>> records = new List<Dictionary<string, object>>();

if (databricksResponse?.Result != null)
{
    var arrayData = databricksResponse.Result[DataArray].ToList();
    List<ColumnSchema> columnsList = databricksResponse.Manifest.Schema.Columns.ToList();

    foreach (var rowData in arrayData)
    {
        var row = rowData.ToList();
        var record = new Dictionary<string, object>();
        for (int j = 0; j < columnsList.Count; j++)
        {
            record[columnsList[j].Name] = row[j];
        }
        records.Add(record);
    }
}

return await Task.FromResult(records);

方法2:正确操作ExpandoObject

ExpandoObject本质实现了IDictionary<string, object>接口,不能直接用动态类型的索引器赋值,需要先转为字典类型:

// 替换原代码中创建record的逻辑
dynamic record = new ExpandoObject();
var recordDict = (IDictionary<string, object>)record;

// 赋值时使用字典的索引器
recordDict[column.Name] = row[j];

方法3:为动态键对象创建接口

由于键是动态生成的,接口无法定义固定属性,只能提供通用的键值访问能力:

public interface IDynamicRecord
{
    object this[string key] { get; set; }
    IEnumerable<string> GetKeys();
    bool ContainsKey(string key);
}

// 基于Dictionary实现该接口
public class DictionaryDynamicRecord : IDynamicRecord
{
    private readonly Dictionary<string, object> _data = new Dictionary<string, object>();

    public object this[string key]
    {
        get => _data[key];
        set => _data[key] = value;
    }

    public IEnumerable<string> GetKeys() => _data.Keys;

    public bool ContainsKey(string key) => _data.ContainsKey(key);
}

使用时直接实例化DictionaryDynamicRecord替代原有动态对象:

var record = new DictionaryDynamicRecord();
record[column.Name] = row[j];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:35:01