Da Task<T>
stammt aus Task
Sie nur, dass abwarten kann, sobald die Aufgabe abgewartet Sie Reflektion verwenden können sicher die .Result
Eigenschaft über Reflexion zuzugreifen.
Sobald Sie das Ergebnis haben, müssen Sie es entweder in einem IBar
speichern und die Methoden und Eigenschaften dafür verwenden oder nach dem Testen auf den spezifischen Typ umwandeln, um die typspezifischen Methoden zu verwenden.
Hier eine vollständige MCVE davon ist
using System;
using System.Reflection;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Test().Wait();
Console.ReadLine();
}
static async Task Test()
{
var foo = new Foo();
var bar2 = new Bar2();
object resultObject = await CallGetByReflection(foo, bar2);
IBar result = (IBar)resultObject;
result.WriteOut();
//or
if (resultObject is Bar)
{
((Bar)resultObject).Something();
}
else if (resultObject is Bar2)
{
((Bar2)resultObject).SomethingElse();
}
}
private static async Task<object> CallGetByReflection(IFoo foo, IBar bar)
{
var method = typeof(IFoo).GetMethod(nameof(IFoo.Get));
var generic = method.MakeGenericMethod(bar.GetType());
var task = (Task) generic.Invoke(foo, new[] {bar});
await task.ConfigureAwait(false);
var resultProperty = task.GetType().GetProperty("Result");
return resultProperty.GetValue(task);
}
public interface IBar
{
void WriteOut();
}
public class Bar : IBar
{
public void Something()
{
Console.WriteLine("Something");
}
public void WriteOut()
{
Console.WriteLine(nameof(Bar));
}
}
public class Bar2 : IBar
{
public void SomethingElse()
{
Console.WriteLine("SomethingElse");
}
public void WriteOut()
{
Console.WriteLine(nameof(Bar2));
}
}
public interface IFoo
{
Task<T> Get<T>(T o) where T : IBar;
}
public class Foo : IFoo
{
public async Task<T> Get<T>(T o) where T : IBar
{
await Task.Delay(100);
return o;
}
}
}
}
UPDATE: Hier ist eine Erweiterung Methode den Prozess
public static class ExtensionMethods
{
public static async Task<object> InvokeAsync(this MethodInfo @this, object obj, params object[] parameters)
{
var task = (Task)@this.Invoke(obj, parameters);
await task.ConfigureAwait(false);
var resultProperty = task.GetType().GetProperty("Result");
return resultProperty.GetValue(task);
}
}
Das macht CallGetByReflection
um
private static Task<object> CallGetByReflection(IFoo foo, IBar bar)
{
var method = typeof(IFoo).GetMethod(nameof(IFoo.Get));
var generic = method.MakeGenericMethod(bar.GetType());
return generic.InvokeAsync(foo, new[] {bar});
}
zu vereinfachen
UPDATE 2: Hier ist eine neue Erweiterung Methode ist, die mit dynamic
und GetAwaiter()
public static class ExtensionMethods
{
public static async Task<object> InvokeAsync(this MethodInfo @this, object obj, params object[] parameters)
{
dynamic awaitable = @this.Invoke(obj, parameters);
await awaitable;
return awaitable.GetAwaiter().GetResult();
}
}
Die Antwort ist zu werfen es statt nur Aufgaben mit jedem awaitable Typ arbeitet, da es ein Objekt zurückgibt (siehe @Fabio). Allerdings sollten Sie sicherstellen, dass "Foo" 'IFoo' erbt, andernfalls erhalten Sie eine Ausnahme, weil' foo' (geliefert am 'Invoke') der falsche Typ ist. – joell
Mögliches Duplikat von [Wie kann man auf eine private asynchrone Methode warten, die durch Reflektion in WinRT aufgerufen wird?] (Http://stackoverflow.com/questions/14711585/how-to-await-an-async-private-method-invoked-using-using-) reflection-in-winrt) – Fabio