mardi 28 mai 2019

Use type to access properties instead of concrete instance

I'm having trouble figuring out how to ask this question (the title is not worded well), so let me start with an example using the NameOf() method, because it does something similar to what I'm trying to accomplish.

If I have a class like this:

Public Class MyClass
    Public Property Foo As Bar
End Class

and then I declare an instance of it Dim instance As New MyClass, I can then use the NameOf() method in one of two ways:

' Both of these lines will print "Foo"
Console.WriteLine(NameOf(instance.Foo))
Console.WriteLine(NameOf(MyClass.Foo))

I would like to implement a method that can accept similar types of parameters, but I cannot figure out how. Here is the (extension) method I wrote:

<Extension()>
Public Function GetPathOfProperty(Of T As Class, TProp)(myObj As T, prop As Expression(Of Func(Of TProp))) As String
    Dim result As String = String.Empty
    Dim foundName As String = String.Empty
    Dim className As String = myObj.GetType().Name
    Dim p As MemberExpression = TryCast(prop.Body, MemberExpression)

    While p IsNot Nothing
        If className = p.Member.DeclaringType.Name Then
            foundName = className + "."
        End If

        result = foundName + p.Member.Name + "." + result
        If Not String.IsNullOrEmpty(foundName) Then
            Exit While
        End If
        p = TryCast(p.Expression, MemberExpression)
    End While

    Return IIf(String.IsNullOrEmpty(foundName), "", result.Substring(0, result.Length - 1))
End Function

Using my above example, I can use it like this:

' Prints "MyClass.Foo"
Console.WriteLine(instance.GetPathOfProperty(Function() instance.Foo)) 
' Prints "MyClass.Foo.SomeBarProperty"
Console.WriteLine(instance.GetPathOfProperty(Function() instance.Foo.SomeBarProperty)) 

I would like to create another version of this method that is not an extension method, but rather a static method that can be called like (or similar to) this:

Console.WriteLine(GetPathOfProperty(Function() MyClass.Foo) ' Prints "MyClass.Foo"

This way I'd be able to use the function without actually creating an instance of MyClass first. And this is where I need help. Since MyClass is not a static class, I'm not able to put MyClass.Foo in the function call. My first thought was to use Reflection, but I can't figure out how. Is there a parameter type I could use to allow me to do this (and if so, how would that look)? Or is this just a pipe-dream and not possible?





Aucun commentaire:

Enregistrer un commentaire