samedi 20 août 2022

C# calling Reactive/ReactiveUI extension methods via reflection

I'm trying to call the equivalent of this code via reflection:

prop.WhenAnyValue(s => s.Value).Skip(1).Subscribe(...);

This is the reflection code I use to "solve" the WhenAnyValue part:

MethodInfo[] whenAnyMethods = typeof(WhenAnyMixin).GetMethods();
MethodInfo whenAnyMethod = new Func<MethodInfo>(() =>
{
    foreach (var mi in whenAnyMethods)
    {
        if (mi.Name == "WhenAnyValue" && mi.GetGenericArguments().Length == 2)
        {
            return mi;
        }
    }

    return null;
})();

MethodInfo whenAnyMethodGeneric = whenAnyMethod.MakeGenericMethod(new Type[] { containingType, propertyType });
var whenAnyResult = whenAnyMethodGeneric.Invoke(null, new object[] { containingObject, expression });

The containing object derives from ReactiveObject (ReactiveUI).

The type of the result is exactly the same as when I'm calling WhenAnyValue directly on a property I'm interested in (without reflection), so I think I got this part right. :)

Now I'm trying to skip:

MethodInfo[] methods = typeof(Observable).GetMethods();
MethodInfo skipMethod = new Func<MethodInfo>(() =>
{
    foreach (var mi in methods)
    {
        if (mi.Name == "Skip" && mi.GetParameters().Length == 2 && mi.GetParameters()[1].ParameterType == typeof(int))
        {
            return mi;
        }
    }

    return null;
})();

MethodInfo skipMethodGeneric = skipMethod.MakeGenericMethod(new Type[] { whenAnyResult.GetType() });
var skipResult = skipMethodGeneric.Invoke(null, new object[] { whenAnyResult, 1 }); <<< this line throws the exception

On execution of the last line an exception is thrown:

System.ArgumentException: "Object of type 'System.Reactive.Linq.ObservableImpl.Select`2+Selector[ReactiveUI.IObservedChange`2[type1,type2],type3]' cannot be converted to type 'System.IObservable`1[System.Reactive.Linq.ObservableImpl.Select`2+Selector[ReactiveUI.IObservedChange`2[type1,type2],type3]]'."

And here I'm stuck. What am I missing?





Aucun commentaire:

Enregistrer un commentaire