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

C#中如何用表达式创建泛型列表并调用Add、ToArray方法?

问题描述

我想编写一个UserData类,用来把任意用户自定义类存储到强类型列表中。比如用户自定义类可以是:

class UserInfo
{
    public int Id {get;set;}
    // 其他属性
}

或者

class BookInfo
{
    public Guid BookId {get;set;}
    public string BookName {get;set;}
    // 其他属性
}

我自己写的UserData类大致如下:

internal class UserData
{
    private readonly bool _isCollection;

    private readonly Type _userEntityType;

    private Expression _list;

    private someDelegeAdd _add;

    private someDelegeToArray _ToArray;

    public UserData(bool isCollection, Type userEntityType)
    {
        _isCollection = isCollection;
        _userEntityType = userEntityType;
        Make();
    }

    private void Make()
    {
        var genericListType = typeof(List<>).MakeGenericType(_userEntityType);
        _list = Expression.New(genericListType);

        var addDefinition = genericListType.GetMethod("Add", new[] { _userEntityType });
        var parameter = Expression.Parameter(_userEntityType);
        var addMethodExp = Expression.Call(_list, addDefinition, parameter);

        _add = Expression.Lambda<Action>(addMethodExp, parameter).Compile(); // 这里的Action有问题
    }

    internal void Add(object data)
    {
        // 不知道怎么调用_add
    }

    internal object GetValue()
    {
        return _isCollection ? _list?? : _ToArray?? ; // 不知道怎么处理ToArray
    }
}

我搜了很久,只找到Func<T,X>相关的委托示例,不清楚怎么创建对应任意类型的Action委托,同时也不知道如何通过表达式调用ToArray方法。

---更新---
使用示例:

if (!cache.Contains(userEntityType))
{
    var userData = new UserData(false, userEntityType);
    // 后续操作
}
解决方案

1. 核心修正点

  • 把_list从Expression类型改为存储实际的强类型List实例(用object类型承载,因为编译期无法确定泛型参数)
  • 用Action<object>存储Add委托,直接兼容外部传入的object类型参数
  • 通过反射获取Enumerable.ToArray<T>方法,构建转换数组的委托

完整修正代码

internal class UserData
{
    private readonly bool _isCollection;
    private readonly Type _userEntityType;
    private object _listInstance; // 存储实际的强类型List实例
    private Action<object> _addAction; // 处理Add逻辑的委托
    private Func<object> _toArrayFunc; // 处理ToArray逻辑的委托

    public UserData(bool isCollection, Type userEntityType)
    {
        _isCollection = isCollection;
        _userEntityType = userEntityType;
        Initialize();
    }

    private void Initialize()
    {
        // 创建强类型List实例
        var genericListType = typeof(List<>).MakeGenericType(_userEntityType);
        _listInstance = Activator.CreateInstance(genericListType);

        // 构建Add委托:将object参数转换为目标类型后调用List.Add
        var addMethod = genericListType.GetMethod("Add", new[] { _userEntityType });
        var addParam = Expression.Parameter(typeof(object), "data");
        var convertedParam = Expression.Convert(addParam, _userEntityType);
        var addCall = Expression.Call(Expression.Constant(_listInstance), addMethod, convertedParam);
        _addAction = Expression.Lambda<Action<object>>(addCall, addParam).Compile();

        // 构建ToArray委托:调用Enumerable.ToArray<T>转换List为数组
        var toArrayMethod = typeof(Enumerable).GetMethod("ToArray")
            .MakeGenericMethod(_userEntityType);
        var toArrayCall = Expression.Call(toArrayMethod, Expression.Constant(_listInstance));
        _toArrayFunc = Expression.Lambda<Func<object>>(toArrayCall).Compile();
    }

    internal void Add(object data)
    {
        _addAction?.Invoke(data);
    }

    internal object GetValue()
    {
        // 根据_isCollection标记返回List实例或数组
        return _isCollection ? _listInstance : _toArrayFunc?.Invoke();
    }
}

关键逻辑说明

  • List实例创建:直接用Activator.CreateInstance生成强类型List实例,比表达式树更简洁直接
  • Add委托处理:通过Expression.Convert自动完成object到目标实体类型的转换,兼容外部传入的任意对象
  • ToArray委托处理:反射获取泛型的ToArray方法,针对当前实体类型构建具体调用,最终返回强类型数组(以object形式承载)

实际使用示例

// 假设cache是存储UserData的字典
var cache = new Dictionary<Type, UserData>();
var userEntityType = typeof(UserInfo);

if (!cache.ContainsKey(userEntityType))
{
    var userData = new UserData(false, userEntityType);
    cache.Add(userEntityType, userData);
}

// 添加数据
var userInfo = new UserInfo { Id = 1001 };
cache[userEntityType].Add(userInfo);

// 获取转换后的数组
var userArray = (UserInfo[])cache[userEntityType].GetValue();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:22:51