C#解析泛型类型

时间:2017-04-05 21:14:46

标签: c# generics dependency-injection autofac

我正在玩一个测试项目。我正在尝试实现CQS模式,我正在接近完成初始测试。我在尝试解决IQueryValidtor<>IQueryHandler<,>课程时遇到了问题。该方法可以解决它们,但是当我尝试访问具体类中实现的接口方法时,我得到了

  

“MyProjectsNamespace.GetSiteValidator.Validate(MyProjectsNamespace.Queries.GetSite)”的最佳重载方法匹配包含一些无效参数。

我的代码基于this answer I found。在设计时,一切似乎都在排队,但是运行时间是另一回事。

我在这个问题上包含了我正在处理的所有接口,实现和单元测试。第一次单元测试实际上正在运行。实际上是尝试使用已解析的类的最后两个。我正在使用Autofac进行依赖注入。

public interface IQuery<TResult> {
}

public class GetSite : IQuery<Site> {
    public Guid Id { get; set; }
}

public interface IValidator<T> {
    Task<List<ValidationResult>> Validate(T command);
}

public class GetSiteValidator : IValidator<GetSite> {
    public async Task<List<ValidationResult>> Validate(GetSite command) {
        List<ValidationResult> results = new List<ValidationResult>();

        if(command == null) {
            throw new ArgumentNullException(nameof(command));
        }

        if(command.Id == Guid.Empty) {
            results.Add(new ValidationResult() { FieldName = "Id", Message = "Is empty" });
        }

        return results;
    }
}

public interface IQueryHandler<in TQuery, TResult> where TQuery : IQuery<TResult> {
    Task<TResult> Handle(TQuery query);
}

public class GetSiteHandler : IQueryHandler<GetSite, Site> {
    public Task<Site> Handle(GetSite query) {
        throw new NotImplementedException();
    }
}

上面的代码是此问题中使用的所有接口和具体类。下面的代码是我遇到问题的调度员类。

public class QueryDispatcher : IQueryDispatcher {
    private readonly IComponentContext _context;

    public QueryDispatcher(IComponentContext context) {
        _context = context;
    }

    public async Task<TResult> Dispatch<TResult>(IQuery<TResult> query) {
        if (query == null) {
            throw new ArgumentNullException(nameof(query), "Query cannot be null");
        }

        // use dynamic datatype because the tresult is not known at compile time
        var validatorType = typeof(IValidator<>).MakeGenericType(query.GetType());
        dynamic validator = _context.Resolve(validatorType);

        var handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult));
        dynamic handler = _context.Resolve(handlerType);

        List<ValidationResult> errors = await validator.Validate(query);

        if(errors.Count == 0) {
            return await handler.Handle(query);
        } else {
            // raise failed validation event
            throw new ApplicationException("Not implemented");
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您正在将IQuery<TResult> query对象传递给Validate(GetSite)方法 - 该方法需要GetSite类型。

即使GetSite实现IQuery<TResult>,编译器也不能保证IQuery<TResult> queryGetSite类型的对象 - 它也可能是其他类型的实现IQuery<TResult>无法进行演员表。