【问题标题】:How to create delegate for Result property getter in Task c#如何在任务 c# 中为 Result 属性获取器创建委托
【发布时间】:2017-05-21 13:58:45
【问题描述】:

我需要在 c#(TResult getter_Result) 中为 Task 的 Result 属性创建一个委托 我可以获取属性 Result 的 getter 方法

Resultgetter = (TaskGenericType).GetProperty("Result").GetGetMethod();

但要将其添加到 delegate ,以下是我的尝试。 我的尝试:

  Delegate d = Delegate.CreateDelegate(typeof(MyDelegate), Resultgetter, true);

代表的签名是

public delegate object MyDelegate();

但这里的问题是: 我不能将“object”作为我的代表的回报,因为签名必须与 Result 属性匹配。 当我尝试编写 TResult 作为我的委托 (public 委托 TResult MyDelegate()) 的返回时,我收到 TResult 无法解析符号的错误。 如何为任务对象的getter_Result 创建委托。

我正在尝试做的事情: 1.获取Task对象Result的getter方法。并在一个事件完成后调用该吸气剂。

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

示例代码

有问题的代码行是

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);
    }


}

示例我如何获取“IsCompleted”属性

 foreach (var x in vals)
            {
                if (x.ToString().Contains("IsCompleted"))
                {
                    try
                    {
                        Resultgetter = TaskType.GetProperty("IsCompleted").GetGetMethod();
                      //  Delegate d = Delegate.CreateDelegate(typeof(MyDelegate), Resultgetter, true);
                        Func<bool> testFunc = Delegate.CreateDelegate(typeof(Func<bool>), null, Resultgetter) as Func<bool>;

                        Console.WriteLine(10);
                    }

                     catch (Exception e)
                    {

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

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

【问题讨论】:

  • 您可能需要使用Type.MakeGenericType,但很难准确判断您仅使用 sn-ps 在做什么。请提供minimal reproducible example
  • @JonSkeet :提供了我想要做什么的解释。谢谢
  • 解释不是我要求的 - 我要求minimal reproducible example。当我们可以重现问题时,我们可以尝试修复它。
  • @JonSkeet 当然。添加了重现问题的示例代码。
  • 好吧,目前您正在尝试为Task&lt;int&gt;Result 属性创建一个返回类型为Task&lt;string&gt; 的委托 - 该Result 属性的类型只是@ 987654338@,不是Task 的任何东西......

标签: c# .net task task-parallel-library


【解决方案1】:

您可以通过表达式树来做到这一点,但是您的示例代码的设置方式让您看起来只是一个Func&lt;object&gt;,这意味着任务必须已经嵌入到表达树。你可以这样做:

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());    
    }
}

如果你想这样做,你还不如直接调用 Result 进行反射,然后构建一个返回的委托:

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
    }
}

这些看起来都不是我特别满意的,但希望你能从中得到一些有用的东西......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    • 2011-08-18
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 2017-01-18
    相关资源
    最近更新 更多