jeudi 10 décembre 2020

Returning a generic type without T at compile time

I have a list of generics defined like so:

class Registrations
{
    private readonly List<MetaRegistration> _registrations = new List<MetaRegistration>();

    private abstract class MetaRegistration
    {
    }

    private class Registration<T> : MetaRegistration
    {
        public async Task<T> Resolve(string value)
        {
            return await ...
        }
    }
}

And I'd like to run a method on one of the Registration<T> instances.

I can easily do it like this if I know the type at compile time:

public async Task<T> Resolve<T>(string value)
{
    var registration = _registrations.Cast<Registration<T>>()
        .First(r => r.GetType().GenericTypeArguments[0] == typeof(T));
    var model = await registration.Resolve(value);
    return model;
}

But how would I go about this without when I don't know T?

Right now, this is how I've come around the problem using reflection, where I know the Type, but only during runtime:

public async Task<object?> Resolve(Type type, string value)
{
    foreach (var metaRegistration in _registrations)
    {
        Type t = metaRegistration.GetType();
        if (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(Registration<>) ||
            t.GenericTypeArguments[0] != type) continue;
        var methodInfo = metaRegistration.GetType().GetMethod("Resolve");
        var test = await (dynamic) methodInfo?.Invoke(metaRegistration, new object?[] {value})!;
        return test;
    }

    return null;
}

However, I would prefer to avoid reflection together, and this feels like I'm doing something incorrectly.

Is there any other way to go about this?





Aucun commentaire:

Enregistrer un commentaire