C# 如何在任务c中为结果属性getter创建委托#

C# 如何在任务c中为结果属性getter创建委托#,c#,.net,task,task-parallel-library,C#,.net,Task,Task Parallel Library,我需要为c#(TResult getter#u Result)中任务的Result属性创建一个委托 我能够得到属性结果的getter方法 Resultgetter = (TaskGenericType).GetProperty("Result").GetGetMethod(); 但要将此添加到委派中,以下是我的尝试。 我的尝试: Delegate d = Delegate.CreateDelegate(typeof(MyDelegate), Resultgetter, true); 代表

我需要为c#(TResult getter#u Result)中任务的Result属性创建一个委托 我能够得到属性结果的getter方法

Resultgetter = (TaskGenericType).GetProperty("Result").GetGetMethod();
但要将此添加到委派中,以下是我的尝试。 我的尝试:

  Delegate d = Delegate.CreateDelegate(typeof(MyDelegate), Resultgetter, true);
代表签字为:

public delegate object MyDelegate();
但这里的问题是: 我不能将“
对象
”作为委托的返回,因为签名必须与结果属性匹配。 当我尝试将
TResult
作为我的委托
public delegate TResult MyDelegate()
的返回写入时,我遇到了一个错误,TResult无法解析该符号。 如何为任务对象的
getter\u Result
创建委托

我想做的是: 1.获取任务对象结果的getter方法。并在一个事件完成后调用该getter

所以在这个过程中。1我能够获得结果的getter。但由于参数不匹配,当我需要分配给委托时面临问题。因此,我需要了解如何为结果提供返回类型

示例代码

有问题的代码行是

Delegate d=Delegate.CreateDelegate(typeof(MyDelegate),Resultgetter,true); 它会在那里流行

catch中的堆栈跟踪为

System.ArgumentException: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
   at System.Delegate.CreateDelegate(Type type, MethodInfo method, Boolean throwOnBindFailure)
   at getProperties.Program.Main(String[] args) in Program.cs:line 126



using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

public delegate Task<string> MyDelegate();


class Program
{


    static void Main(string[] args)
    {
        Task<int> task1 = Task<int>.Factory.StartNew(() => 1);
        int i = task1.Result;

        PropertyInfo[] vals = GetPublicProperties(task1.GetType());
        Type TaskGenericType = Type.GetType("System.Threading.Tasks.Task`1");
        MethodInfo Resultgetter;
        foreach (var x in vals)
        {
            if (x.ToString().Contains("Result"))
            {
                try
                {
                    Resultgetter = (TaskGenericType).GetProperty("Result").GetGetMethod();
                    ***Delegate d = Delegate.CreateDelegate(typeof(MyDelegate), Resultgetter, true);***
                }

                catch (Exception e)
                {

                    Console.WriteLine(e);
                    Console.WriteLine(e.StackTrace);
                    throw;
                }

            }
            Console.WriteLine(x.ToString());
        }


    }


    static PropertyInfo[] GetPublicProperties(Type type)
    {
        if (type.IsInterface)
        {
            var propertyInfos = new List<PropertyInfo>();

            var considered = new List<Type>();
            var queue = new Queue<Type>();
            considered.Add(type);
            queue.Enqueue(type);
            while (queue.Count > 0)
            {
                var subType = queue.Dequeue();
                foreach (var subInterface in subType.GetInterfaces())
                {
                    if (considered.Contains(subInterface)) continue;

                    considered.Add(subInterface);
                    queue.Enqueue(subInterface);
                }

                var typeProperties = subType.GetProperties(
                    BindingFlags.FlattenHierarchy
                    | BindingFlags.Public
                    | BindingFlags.Instance);

                var newPropertyInfos = typeProperties
                    .Where(x => !propertyInfos.Contains(x));

                propertyInfos.InsertRange(0, newPropertyInfos);
            }

            return propertyInfos.ToArray();
        }

        return type.GetProperties(BindingFlags.FlattenHierarchy
            | BindingFlags.Public | BindingFlags.Instance);
    }


}
System.ArgumentException:无法绑定到目标方法,因为其签名或安全透明性与委托类型的签名或安全透明性不兼容。
在System.Delegate.CreateDelegate(类型类型,MethodInfo方法,布尔throwOnBindFailure)
在Program.cs中的getProperties.Program.Main(字符串[]args)处:第126行
使用制度;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
使用System.Threading.Tasks;
公共委托任务MyDelegate();
班级计划
{
静态void Main(字符串[]参数)
{
Task task1=Task.Factory.StartNew(()=>1);
int i=任务1.结果;
PropertyInfo[]VAL=GetPublicProperties(task1.GetType());
Type TaskGenericType=Type.GetType(“System.Threading.Tasks.Task`1”);
方法信息结果更好;
foreach(var x以VAL为单位)
{
如果(x.ToString()包含(“结果”))
{
尝试
{
Resultgetter=(TaskGenericType).GetProperty(“结果”).GetMethod();
***Delegate d=Delegate.CreateDelegate(typeof(MyDelegate),Resultgetter,true)***
}
捕获(例外e)
{
控制台写入线(e);
控制台写入线(如StackTrace);
投掷;
}
}
Console.WriteLine(x.ToString());
}
}
静态属性信息[]GetPublicProperties(类型)
{
if(类型IsInterface)
{
var propertyInfos=新列表();
var=newlist();
var queue=新队列();
添加(类型);
队列。排队(类型);
而(queue.Count>0)
{
var subType=queue.Dequeue();
foreach(子类型.GetInterfaces()中的var子接口)
{
如果(考虑包含(子接口))继续;
添加(子接口);
排队(子接口);
}
var typeProperties=subType.GetProperties(
BindingFlags.FlatterHierarchy
|BindingFlags.Public
|BindingFlags.Instance);
var newPropertyInfos=类型属性
其中(x=>!propertyInfos.Contains(x));
propertyInfos.InsertRange(0,newPropertyInfos);
}
返回属性inFos.ToArray();
}
返回类型.GetProperties(BindingFlags.Strearchy)
|BindingFlags.Public | BindingFlags.Instance);
}
}
示例如何获取“IsCompleted”属性

foreach(var x在VAL中)
{
如果(x.ToString()包含(“IsCompleted”))
{
尝试
{
Resultgetter=TaskType.GetProperty(“IsCompleted”).GetMethod();
//Delegate d=Delegate.CreateDelegate(typeof(MyDelegate),Resultgetter,true);
Func testFunc=Delegate.CreateDelegate(typeof(Func),null,Resultgetter)作为Func;
控制台写入线(10);
}
捕获(例外e)
{
控制台写入线(e);
控制台写入线(如StackTrace);
投掷;
}
}
Console.WriteLine(x.ToString());
}

您可以通过表达式树来实现这一点,但示例代码的设置方式使您看起来只需要一个
函数,这意味着任务必须已经嵌入到表达式树中。你可以这样做:

using System;
using System.Linq.Expressions;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        Task<int> task = Task.FromResult(1);

        var constantExpression = Expression.Constant(task, task.GetType());
        var propertyExpression = Expression.Property(constantExpression, "Result");
        var conversion = Expression.Convert(propertyExpression, typeof(object));
        var lambda = Expression.Lambda<Func<object>>(conversion);
        Func<object> compiled = lambda.Compile();

        Console.WriteLine(compiled());    
    }
}

对我来说,这两种方法都不是特别令人满意,但希望你能从中得到一些有用的东西…

你可能需要使用
Type.MakeGenericType
,但很难准确地说出你只使用片段做了什么。请提供一个解释。@JonSkeet:提供了我试图做什么的解释。谢谢你的解释不是我要的-我要的是一个解释。“当我们可以重现这个问题时,我们可以试着去解决它。”琼斯凯说。添加了示例代码以重现该问题。目前,您正在尝试创建一个返回类型为
任务
的委托,用于
任务
结果
属性-该
结果
属性的类型只是
int
,而不是
任务
。。。
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        Task<int> task = Task.FromResult(1);

        var constantExpression = Expression.Constant(task, task.GetType());
        var propertyExpression = Expression.Property(constantExpression, "Result");
        var conversion = Expression.Convert(propertyExpression, typeof(object));
        var lambda = Expression.Lambda<Func<object>>(conversion);
        Func<object> compiled = lambda.Compile();

        Console.WriteLine(compiled());    
    }
}
using System;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        // Compile-time type object to prove I'm not cheating...
        object task = Task.FromResult(1);

        var result = task.GetType().GetProperty("Result").GetValue(task);

        Func<object> d = () => result;
        Console.WriteLine(d()); // 1
    }
}