.net 检查对象是任务还是任务< TResult>

cnh2zyt3  于 2022-12-14  发布在  .NET
关注(0)|答案(6)|浏览(163)

在下面的示例代码中(由于if检查无效,所以无法编译),我需要确定returnValue是“TResult的任务”还是任务或其他类型。如果是TResult的任务,我可以访问并记录Result属性,如果是任务,则没有返回值,我记录“[Task]",如果两者都不是,则我可以直接记录返回值或记录[“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属性,但我不确定是否始终有效。

iih3973s

iih3973s1#

尽管Eric Lippert提到您不应该获取Task.Result,但仍有一些问题需要回答:
1.如何检查对象是否为泛型类型

obj.GetType().IsGenericType

1.不管是任务

obj.GetType().GetGenericTypeDefinition() == typeof(Task<>)

1.如何访问泛型属性值

obj.GetType().GetProperty("Result").GetValue(obj) // This value could be null
jei2mxaa

jei2mxaa2#

可能有一个更干净的方法,但这是可行的,你可以在它的基础上构建。“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);
        }
    }
}
svdrlsy4

svdrlsy43#

我觉得要么前面的回答都没有清楚地回答被问到的问题,要么我宁愿错过了问题意图的标记。
我对这个问题的理解是:

  • “如何判断'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
h5qlskok

h5qlskok4#

让我们保持简单,好吗?这个方法会给予你这样的想法:

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,它工作正常。

e0uiprwp

e0uiprwp5#

我注意到,在**.Net 5中,从来不需要null属性访问器?.,因为Result**属性对所有任务都存在。它被初始化为System.Threading.Tasks.VoidTaskResult。这不是获取值的最有效方法,但它很简洁。

var result = task.GetType().GetProperty(nameof(Task<object>.Result))?.GetValue(task);
voase2hg

voase2hg6#

这可能会有帮助。
用途:

Type type = abc.GetType().GetProperty("Item").PropertyType

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

相关问题