检查对象是否为任务或任务<tresult>

时间:2017-10-17 00:33:29

标签: c# .net async-await task

在下面的示例代码中(因为检查无效而无法编译)我需要弄清楚returnValue是否是&#34; TResult的任务&#34;或任务或其他类型。如果它是TResult的任务我可以访问并记录结果属性,如果它是任务,则没有返回值,我记录了#34; [任务]&#34;,如果它&#39; ; s这两个都不是我可以直接记录返回值或记录[&#34; null&#34;]

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属性,但我不确定   如果那将永远有效。

6 个答案:

答案 0 :(得分:9)

尽管Eric Lippert提到你不应该获取Task.Result,但仍有几个问题要回答:

  1. 如何检查对象是否为泛型类型

    obj.GetType().IsGenericType
    
  2. 是否为任务&lt; TResult&gt;

    obj.GetType().GetGenericTypeDefinition() == typeof(Task<>)
    
  3. 如何访问通用属性值

    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?