在下面的示例代码中(因为检查无效而无法编译)我需要弄清楚returnValue是否是" TResult的任务"或任务或其他类型。如果它是TResult的任务我可以访问并记录结果属性,如果它是任务,则没有返回值,我记录了#34; [任务]",如果它' ; s这两个都不是我可以直接记录返回值或记录[" null"]
public void LogReturnValue(obj returnValue)
{
var valueToLog = "";
if(returnValue is Task)
{
valueToLog = "[Task]";
} else if(returnValue is Task<T>)
{
valueToLog = returnValue.Result;
}
else
{
valueToLog = returnValue ?? "[null]"
}
this.logger.Log(valueToLog);
}
我想确定returnValue是否是TResult的任务或任务,然后如果是后者,我需要从Result中提取适当的值。一 我的想法是检查IsGenericType属性,但我不确定 如果那将永远有效。
答案 0 :(得分:9)
尽管Eric Lippert提到你不应该获取Task.Result,但仍有几个问题要回答:
如何检查对象是否为泛型类型
obj.GetType().IsGenericType
是否为任务&lt; TResult&gt;
obj.GetType().GetGenericTypeDefinition() == typeof(Task<>)
如何访问通用属性值
obj.GetType().GetProperty("Result").GetValue(obj) // This value could be null
答案 1 :(得分:2)
可能有一种更清洁的方式,但这有效,你可以在它上面建立。 &#34;如&#34;将检查类型或基类型是否为任务,然后您可以检查类型以查看它是否具有泛型类型参数。因为它是动态的,所以对Result属性的检查是在运行时而不是编译时完成的。
static void outType(object returnValue)
{
dynamic task = returnValue as Task;
if ( task != null )
{
var gargs = returnValue.GetType().GenericTypeArguments;
if (gargs.Count() == 0)
{
Console.WriteLine("Task");
}
else
{
var result = task.IsCompleted ? task.Result : "[Not Complete]";
Console.WriteLine("Task<{0}> : {1}", gargs[0].Name, result);
}
}
}
答案 2 :(得分:0)
我觉得前面的回答都没有清楚地回答所提出的问题,或者我想念这个问题的意图。
我从问题中得到的解释是:
”“如何确定'returnValue'是'Task','Task <>'还是其他类型?
此测试代码可用于确定以下内容:
Task voidTask = new Task(() => { return; });
Task<object> valTask = new Task<object>(() => { return null; });
Type voidTaskType = voidTask.GetType();
Type valTaskType = valTask.GetType();
Console.WriteLine($"voidTaskType is Task : {voidTask is Task}");
Console.WriteLine($"valTaskType is Task : {valTask is Task}");
Console.WriteLine($"voidTaskType.IsGenericType : {voidTaskType.IsGenericType}");
Console.WriteLine($"valTaskType.IsGenericType : {valTaskType.IsGenericType}");
结果如下:
voidTaskType is Task : True
valTaskType is Task : True
voidTaskType.IsGenericType : False
valTaskType.IsGenericType : True
答案 3 :(得分:0)
让我们保持简单吧?此方法将为您提供想法:
object GetTaskResult(Task task, out bool hasResult) {
var resultProperty = task.GetType().GetProperty("Result");
hasResult = resultProperty != null;
return hasResult ? resultProperty.GetValue(task) : null;
}
它告诉您任务是否有结果,并返回结果。
替代版本
bool GetTaskResult(Task task, out object result) {
var resultProperty = task.GetType().GetProperty("Result");
if (resultProperty == null) {
result = null;
return false;
}
result = resultProperty.GetValue(task);
return true;
}
我已经为VoidTaskResult
测试了它,并且可以正常工作。
答案 4 :(得分:0)
我注意到在 .Net 5 中从来不需要空属性访问器 ?.
,因为所有任务都存在 Result 属性。它被初始化为 System.Threading.Tasks.VoidTaskResult
。这不是获取价值的最有效方式,但很简洁。
var result = task.GetType().GetProperty(nameof(Task<object>.Result))?.GetValue(task);
答案 5 :(得分:-4)
这可能会有所帮助。
使用:
Type type = abc.GetType()。GetProperty(&#34; Item&#34;)。PropertyType
参考: How to get the type of T from a member of a generic class or method?