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
相关产品推荐
相关产品推荐

