2017-05-23 4 views
1

Aufrufen Sie sich das folgende Erweiterungsmethode:generische Erweiterungsmethode mit Parametern

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

Eine Implementierung von AbstractValidator:

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

Ich möchte die getRules() Erweiterungsmethode auf ValiDoc über Reflexion und Pass aufzurufen in einer Instanz von AddressValidator als der erste Parameter mit einem booleschen Wert für die Sekunde.

Ich habe noch nie zuvor mit Reflection gespielt, aber ich bin ziemlich überwältigt, aber wenn ich die hier verfügbaren Beispiele befolge, habe ich einige Fortschritte gemacht.

//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); 

Wenn generatedGetRules.Invoke Ausführung erhalten I wird folgende Fehlermeldung:

'Objekt des Typs '' nicht konvertiert werden kann eingeben' ValiDoc.Tests.TestData.Validators.AddressValidator FluentValidation .AbstractValidator 1[FluentValidation.AbstractValidator 1 [ValiDoc.Tests.TestData.POCOs.Address]] '.'

Habe ich etwas offensichtlich übersehen? Ich kann nicht sagen, ob ich fast da bin oder Meilen entfernt bin.

Stützwerte.

typeof (AbstractValidator <>) = {FluentValidation.AbstractValidator`1 [T]}

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

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

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

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

EDIT: Arbeits Umsetzung:

// 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(childValidator.ValidatorType.GetTypeInfo().BaseType.GenericTypeArguments[0]); 

       //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 
       var output = generatedGetRules.Invoke(null, parameterArray) as IEnumerable<RuleDescription>; 

Antwort

1

In der Fehlermeldung, ich sehe AddressValidator (AbstractValidator<Address>) kann nicht in AbstractValidator<AbstractValidator<Address>> konvertiert werden, was genau Sie tun. Constructed ist nicht was Sie in MakeGenericMethod übergeben möchten, nehme ich an, da die Methode auf T generisch ist, aber das erste Argument ist this AbstractValidator<T>, so dass Sie eine doppelte generische Spezialisierung erhalten, anstatt was Sie wollen.

+0

Nailed it - Frage mit Antwort aktualisiert. Vielen Dank für Ihre Hilfe :) –

Verwandte Themen