jeudi 18 août 2016

Using reflection to invoke Linq extension method from within reflected invocation of Linq extension method

I have two instances of List(Of String).

And I can call something like this for the data above (which returns False):

ls1.All(Function(v) ls2.Contains(v))

But can this line of code be done entirely via Reflection with a generic method?

Obviously I could make the method take a type of IEnumerable(Of T) rather than just T, but then it wouldn't need to use any Reflection and would be a single line, so for this method, assume it could potentially take types other than IEnumerable to have its way with:

Private Function ComparisonMethod(Of T)(value As T, comparisonValue As T) As Boolean
    If Not GetType(T).GetInterfaces().Any(Function(t2) t2.IsGenericType AndAlso t2.GetGenericTypeDefinition() Is GetType(IEnumerable(Of )))
        Return False 'Not an IEnumerable(Of ).
    End If

    Dim underType As Type = GetType(T).GetInterfaces().Where(Function(t2) t2.IsGenericType AndAlso t2.GetGenericTypeDefinition() Is GetType(IEnumerable(Of ))).First().GetGenericArguments()(0)

    Dim m1 As Reflection.MethodInfo = GetType(Enumerable).GetMethods().Where(Function(m) m.Name = "All" AndAlso m.GetParameters().Count() = 2).First()
    m1 = m1.MakeGenericMethod(underType)

    Dim m2 As Reflection.MethodInfo = GetType(Enumerable).GetMethods().Where(Function(m) m.Name = "Contains").First()
    m2 = m2.MakeGenericMethod(GetType(String))

    Return DirectCast(m1.Invoke(Nothing, {value,    Function(v As Object)
                                                        Return m2.Invoke(Nothing, {comparisonValue, Convert.ChangeType(v, underType)})
                                                    End Function}
                                                ), Boolean)

    Return False

End Function

The line with the invocations fails with the following message because (presumably) a Type of Object isn't the Type that underType has (which in this case is a String):

"Object of type 'VB$AnonymousDelegate_02[System.Object,System.Object]' cannot be converted to type 'System.Func2[System.String,System.Boolean]'."

I don't know how to get v to have the correct type. Is there any way to make that anonymous function take a generic type?

This question is more of a 'can it be done' thing than anything else, rather than whether or not it should be done, as I'm curious whether or not this is actually possible to do.





Aucun commentaire:

Enregistrer un commentaire