How to create delegate for Result property getter in Task c#

I need to create a delegate for Result property of Task in c#( TResult getter_Result) I am able to get getter method for property Result

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

But to add this to delegate , the following are my tries. My tries :

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

The signature of Delegate is

public delegate object MyDelegate();

But the issue here is : I cannot have "object" as return for my delegate, as the signature has to match with Result property. When I tried writing TResult as return for my delegate (public delegate TResult MyDelegate()) , I am getting error that TResult cannot resolve symbol. How to create delegate for getter_Result for Task object.

what I am trying to do : 1.Getting getter method of Result for a Task object . And invoking that getter after one event is done.

So in that process . 1I am able to get getter for Result. But facing issue when I need to assign to delegate because of parameter mismatch. hence , I need to understand how to give return type for Result.

sample code

The problematic code line is

Delegate d = Delegate.CreateDelegate(typeof(MyDelegate), Resultgetter, true); it is going to catch there ,

the stack trace in catch is

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


}

sample How I am fetching "IsCompleted" property

 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());
            }
Jon Skeet
people
quotationmark

You can do this via expression trees, but the way your sample code is set up makes it look like you want just a Func<object>, which means the task has to be already embedded in the expression tree. You can do that:

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

If you want to do that, you might as well just call Result with reflection, and then build a delegate that returns that:

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

Neither of those looks particularly satisfactory to me, but hopefully you'll be able to get something useful out of them...

people

See more on this question at Stackoverflow