C# 如何在任务c中为结果属性getter创建委托#
我需要为c#(TResult getter#u Result)中任务的Result属性创建一个委托 我能够得到属性结果的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); 代表
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
}
}