代码之家  ›  专栏  ›  技术社区  ›  Sushant

检查对象是Task还是Task<TResult>

  •  6
  • Sushant  · 技术社区  · 8 年前

    在下面的示例代码中(由于if检查无效而无法编译),我需要确定returnValue是“TResult任务”还是任务或其他类型。如果它是TResult的任务,我可以访问并记录Result属性,如果它是任务,没有返回值,我记录“[任务]”,如果这两者都不是,那么我可以直接记录返回值或记录[“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的任务,然后如果是后者,我需要从结果中提取适当的值。一 我的想法是检查IsGenericType属性,但我不确定 如果这能一直奏效的话。

    6 回复  |  直到 8 年前
        1
  •  13
  •   qxg    8 年前

    尽管Eric Lippert提到,您不应该获取任务。因此,有几个问题需要回答:

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

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

      obj.GetType().GetProperty("Result").GetValue(obj) // This value could be null
      
        2
  •  2
  •   Tony Lee    8 年前

    也许有一个更干净的方法,但这是可行的,你可以在它的基础上再接再厉。“as”将检查类型或基类型是否为任务,然后可以检查该类型是否具有泛型类型参数。因为它是动态的,所以在运行时而不是编译时检查结果是否为属性。

    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);
            }
        }
    }
    
        3
  •  1
  •   Mitselplik    5 年前

    我觉得前面的答案要么都没有清楚地回答被问到的问题,要么我错过了问题意图的标记。

    我对这个问题的解释是:

    “我如何判断‘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
    
        4
  •  0
  •   Javid    5 年前

    让我们保持简单,好吗?这种方法会让你产生以下想法:

    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 这是可行的。

        5
  •  0
  •   N-ate    5 年前

    .净额5 null属性访问器 ?. 从不需要,因为 后果 属性对于所有任务都存在。它初始化为 System.Threading.Tasks.VoidTaskResult . 这不是获得值的最有效方法,但它很简洁。

    var result = task.GetType().GetProperty(nameof(Task<object>.Result))?.GetValue(task);
    
        6
  •  -4
  •   Shree Harsha    8 年前

    使用:

    类型类型=abc。GetType()。GetProperty(“项目”)。属性类型

    请参阅: How to get the type of T from a member of a generic class or method?

    推荐文章