Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用反射调用通用异步方法_C#_Reflection_Async Await - Fatal编程技术网

C# 如何使用反射调用通用异步方法

C# 如何使用反射调用通用异步方法,c#,reflection,async-await,C#,Reflection,Async Await,我如何等待此任务?如何将其强制转换为任务?根据您的示例,您知道编译时返回对象的类型->IFoo,因此可以使用普通强制转换(IFoo) 但若在运行时任务的类型不是任务,则将抛出异常 如果您需要具体类型的IBar,那么 var method = typeof(IFoo).GetMethod(nameof(IFoo.Get)); var generic = method.MakeGenericMethod(bar2.GetType()); dynamic task = generic.Invoke(f

我如何等待此
任务
?如何将其强制转换为
任务?

根据您的示例,您知道编译时返回对象的类型->
IFoo
,因此可以使用普通强制转换
(IFoo)

但若在运行时任务的类型不是
任务
,则将抛出异常
如果您需要具体类型的
IBar
,那么

var method = typeof(IFoo).GetMethod(nameof(IFoo.Get));
var generic = method.MakeGenericMethod(bar2.GetType());
dynamic task = generic.Invoke(foo, new [] { bar2 });

IBar result = await task;
由于
Task
源于
Task
,因此您可以等待,一旦等待任务,您就可以使用反射通过反射安全地访问
.Result
属性

获得结果后,您需要将其存储在
IBar
中,并使用其上的方法和属性,或者在测试后转换到特定类型以使用特定类型的方法

这里有一个完整的MCVE

var concreteResult = Convert.ChangeType(result, bar2.GetType()); 

更新2:这里有一个新的扩展方法,通过使用
dynamic
GetAwaiter()

公共静态类扩展方法
{
公共静态异步任务InvokeAsync(this MethodInfo@this,object obj,params object[]参数)
{
dynamic awaitable=@this.Invoke(obj,参数);
等待着等待着;
返回awaitable.GetAwaiter().GetResult();
}
}
您可以使用“result”属性来避免使用“wait”关键字,并且不应在方法中标记为“async”

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();
    }
}
var method=typeof(IFoo.GetMethod)(nameof(IFoo.Get));
var generic=method.MakeGenericMethod(typeof(IBar));
var task=(task)generic.Invoke(foo,new[]{bar2});
var resultProperty=task.GetProperty(“结果”);
var result=resultProperty.GetValue(任务);
var convertedResult=Convert.ChangeType(结果,bar2.GetType());

在@ScottChamberlain之上(这很好,答案是强制转换它,因为它返回一个对象(请参见@Fabio)。但是,你应该确保
Foo
确实继承
IFoo
,否则你会得到一个异常,因为
Foo
(在
调用
中提供)类型错误。
var task=(task)generic.Invoke(foo,new[]{bar2});
throws
InvalidCastException
无法将类型为
'System.Threading.Tasks.task'
的对象强制转换为类型
'System.Threading.Tasks.task'
动态任务=generic.Invoke(foo,new[]{bar2});IBar result=wait task;
始终返回
null
@user2321864,而不是执行
method.MakeGenericMethod(bar2.GetType());
您需要执行
method.MakeGenericMethod(typeof(IBar))
那么第一个例子就可以了。
任务
不是协变的,所以你不能将
任务
强制转换为
任务
@user2321864,
动态任务…
获取
方法返回的内容无关。我认为你需要检查
获取
方法的行为。编译器错误CS0656:Der vom编译器angeforderte成员“Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create”fehlt。这指向上一个示例中“return”之后的可等待项。@ygoe将包Microsoft.CSharp添加到项目中请注意
.GetAwaiter().GetResult()
阻止执行控件本身。@Rzassar No它不会,因为我们执行了
wait waitable;
返回waitable.getwaitable().GetResult();
我们保证任务处于完成状态,因此
GetResult()
将是一个非阻塞调用,因为结果将可用。
var method = typeof(IFoo).GetMethod(nameof(IFoo.Get));
var generic = method.MakeGenericMethod(bar2.GetType());
dynamic task = generic.Invoke(foo, new [] { bar2 });

IBar result = await task;
var concreteResult = Convert.ChangeType(result, bar2.GetType()); 
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;
            }
        }
    }
}
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);
    }
}
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});
}
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();
    }
}
var method = typeof(IFoo).GetMethod(nameof(IFoo.Get));
var generic = method.MakeGenericMethod(typeof(IBar));
var task = (Task<IBar>)generic.Invoke(foo, new [] { bar2 });

var resultProperty = task.GetProperty("Result");
var result = resultProperty.GetValue(task);
var convertedResult = Convert.ChangeType(result, bar2.GetType());