使用参数

时间:2017-05-23 20:59:26

标签: c# generics reflection .net-core .net-standard

考虑以下扩展方法:

public static class ValiDoc
{
        public static IEnumerable<RuleDescription> GetRules<T>(this AbstractValidator<T> validator, bool documentNested = false)
        {
             //....
        }
}

AbstractValidator的实现:

public class AddressValidator : AbstractValidator<Address>
{
    public AddressValidator()
    {
        RuleFor(address => address.HouseNumber).NotEmpty();
        RuleFor(address => address.StreetName).NotEmpty();
        RuleFor(address => address.PostCode).NotEmpty();
    }
}

我想通过反射在ValiDoc上调用GetRules()扩展方法,并传入一个AddressValidator实例作为第一个参数,并为第二个参数传递一个布尔值。

在我不知所措之前从未玩过反射,但是通过遵循这里提供的示例,我已经取得了一些进展。

//Parameter 1
Type type = typeof(AbstractValidator<>);

// Instance of Address
Type constructed = type.MakeGenericType(childValidator.ValidatorType.GetTypeInfo().BaseType.GenericTypeArguments[0]);

// Find the extension method based on the signature I have defined for the usage
// public static IEnumerable<RuleDescription> GetRules<T>(this AbstractValidator<T> validator, bool documentNested = false)
var runtimeMethods = typeof(ValiDoc).GetRuntimeMethods();

MethodInfo generatedGetRules = null;

// Nothing fancy for now, just pick the first option as we know it is GetRules
using (IEnumerator<MethodInfo> enumer = runtimeMethods.GetEnumerator())
{
    if (enumer.MoveNext()) generatedGetRules = enumer.Current;
}

// Create the generic method instance of GetRules()
generatedGetRules = generatedGetRules.MakeGenericMethod(constructed);

//Parameter 1 = Derived from AbstractValidator<T>, Parameter 2 = boolean
var parameterArray = new object[] { childValidator.GetValidator(new PropertyValidatorContext(new ValidationContext(rule.Member.DeclaringType), rule, propertyName)), true };

//Invoke extension method with validator instance
generatedGetRules.Invoke(null, parameterArray);

执行generatedGetRules.Invoke时,收到以下错误消息:

  

&#39;对象类型&#39; ValiDoc.Tests.TestData.Validators.AddressValidator&#39;   无法转换为类型   &#39; {FluentValidation.AbstractValidator {1}} 1 [ValiDoc.Tests.TestData.POCOs.Address]]&#39;&#39;

我错过了什么明显的东西吗?我无法判断我是否在那里或几英里之外。

支持值:

typeof(AbstractValidator&lt;&gt;)= {FluentValidation.AbstractValidator`1 [T]}

childValidator.ValidatorType.GetTypeInfo()。BaseType.GenericTypeArguments [0] = {ValiDoc.Tests.TestData.POCOs.Address}

construct = {FluentValidation.AbstractValidator`1 [ValiDoc.Tests.TestData.POCOs.Address]}

generatedGetRules = {System.Collections.Generic.IEnumerable 1[FluentValidation.AbstractValidator 1](FluentValidation.AbstractValidator 1[ValiDoc.Output.RuleDescription] GetRules[AbstractValidator 1 [ValiDoc.Tests.TestData.POCOs.Address]],Boolean)}

参数array = {ValiDoc.Tests.TestData.Validators.AddressValidator},boolean

编辑: 工作实施:

1[FluentValidation.AbstractValidator

1 个答案:

答案 0 :(得分:1)

在您的错误消息中,我看到AddressValidatorAbstractValidator<Address>)无法转换为AbstractValidator<AbstractValidator<Address>>,这正是您正在做的事情。构建是你要传递给MakeGenericMethod的东西,我假设,因为该方法在T上是通用的,但第一个参数是this AbstractValidator<T>所以你得到了双重泛型专业而不是你想要的。