lundi 15 juillet 2019

Call a local generic method by reflection

I need to call a local generic method by reflection, but I can't figure out how to do it.

My core problem is that I'm using reflection to populate an POCO object from a set of queries reading EAV data from a MySQL database. I'm happy to show this code, but it's lengthy and complex. I've created a simplified example that I think summarizes the problem nicely.

Consider this code:

void Main()
{
    var repository = new Repository();
    repository.Store<Foo>(xs => xs.Count());

    int Compute<M>(string[] source) => repository.Fetch<M>().Invoke(source);

    Console.WriteLine(Compute<Foo>(new[] { "A", "B" }));
}

public class Foo { }

public class Repository
{
    private Dictionary<Type, object> _store = new Dictionary<Type, object>();

    public void Store<T>(Func<string[], int> value)
    {
        _store[typeof(T)] = value;
    }

    public Func<string[], int> Fetch<T>()
    {
        return (Func<string[], int>)_store[typeof(T)];
    }
}

I have a Repository type that can store a Func<string[], int> indexed by Type.

In my Main method I have instantiated an instance of Repository and stored xs => xs.Count() against the type Foo.

I have a local generic method Compute that I can call easily when I know the type of M at compile time. The call Compute<Foo>(new[] { "A", "B" }) computes 2. That's no problem.

The issue occurs when I only know M at run-time.

Let's say I have this type:

public class Bar
{
    public Foo Value;
}

Now my code in Main looks like this:

void Main()
{
    var repository = new Repository();
    repository.Store<Foo>(xs => xs.Count());

    int Compute<M>(string[] source) => repository.Fetch<M>().Invoke(source);

    var runtimeType = typeof(Bar).GetField("Value").FieldType;

    var reflectedMethod = /* What Goes Here ??? */

    Console.WriteLine(reflectedMethod.Invoke(new[] { "A", "B" }));
}

I am thoroughly stumped with the /* What Goes Here ??? */ part.

I found a similar question but that method doesn't deal with a local generic method.

Can someone help with how to invoke such a method at run-time?





Aucun commentaire:

Enregistrer un commentaire