首页 > 解决方案 > 如何使用类型列表的参数创建泛型类型的实例

问题描述

我有一个Result看起来像这样的通用类

public class Result<T>
{
    public List<Error> Errors { get; set; } = new List<Error>();

    public T ResultObject { get; set; }

    public Result(List<Error> errors)
    {
        Errors = errors;
        Success = false;
    }
}

我尝试创建一个这样的实例:

public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
    var context = new ValidationContext<TRequest>(request);

    var failures = _validators
        .Select(v => v.Validate(context))
        .SelectMany(result => result.Errors)
        .Where(f => f != null)
        .ToList();

    if (failures.Count != 0)
    {
        var responseType = typeof(TResponse);
        // This is the important line
        return Task.FromResult(Activator.CreateInstance(responseType, new object[] { failures.Select(x => new Error(x.ErrorMessage)).ToList() }) as TResponse);
    }

    return next();
}

TResponse是类型Result<GetUserFlow>GetUserFlow是一个 dto,但在这种情况下并不重要。当我运行我的代码时,我收到以下错误:

System.MissingMethodException:找不到类型“Heimdall.Application.Result`1[[Heimdall.Application.Dtos.GetUserFlow, Heimdall.Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'的构造函数。

我想问题在于,当将列表作为参数传递时,它不是一个参数,而是多个参数。每个创建的错误都是一个参数。我找不到有关此主题的任何内容。

标签: c#listgenericsreflection

解决方案


您可以使用以下方法调用正确的构造函数:

constructorInfo.Invoke(new object[] { failures.Select(x => new Error(x.ErrorMessage)).ToList() }) as TResponse

要获取构造函数,请使用如下内容:

responseType.GetConstructors()[0]
// if you have multiple constructors, ensure the correct one with:
responseType.GetConstructor(new Type[]{ typeof(List<Error>) })

顺便说一句,您可能会发现工厂模式要容易得多。

将工厂委托传递给 Handle 函数Func<List<Errors>, TResponse>,并使用该委托调用构造函数。

public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken,
  RequestHandlerDelegate<TResponse> next, Func<List<Errors>, TResponse> responseCreator)
{
....
    return Task.FromResult(responseCreator(
        failures.Select(x => new Error(x.ErrorMessage)).ToList()
    ));
....
}

你这样称呼它:

 var result = Handle(...., errors => new Result<GetUserFlow>(errors));

推荐阅读