title: Convert Task<object> to Task<T> where T is unknown
body: <p>How can i convert <code>Task&lt;object&gt;</code> to <code>Task&lt;T&gt;</code> where T is unknown?</p>
  
  <p>For example 
  <code>Task&lt;object&gt; to Task&lt;int&gt;</code></p>
  
  <pre><code>interface IAsyncActions
  {
      Task&lt;int&gt; GetValueAsync();
  }
  
  class Proxy : RealProxy
  {
      public Proxy() : base(typeof(IAsyncActions)) { }
  
      public override IMessage Invoke(IMessage msg)
      {
          var call = (IMethodCallMessage)msg;
          var method = (MethodInfo)call.MethodBase;
          if (method.ReturnType.IsSubclassOf(typeof(Task)))
          {
              // return type is Task&lt;T&gt;
              Task taskResult = AsyncMethod2(call);
              return new ReturnMessage(taskResult, null, 0, call.LogicalCallContext, call); // InvalidCastException if taskResult not a Task&lt;int&gt;
          }
          else
          {
              // ...
              return null;
          }
      }
  
      static void Main()
      {
          Proxy p = new Proxy();
          IAsyncActions tProxy = (IAsyncActions)p.GetTransparentProxy();
          int result = tProxy.GetValueAsync().Result; // InvalidCastException
      }
  
      // This method works fine
      Task AsyncMethod(IMethodCallMessage call)
      {
          Task&lt;int&gt; task = Task.FromResult(1234);
          return task;
      }
  
      // This method does not work
      Task AsyncMethod2(IMethodCallMessage call)
      {
          Type taskReturnType = ((MethodInfo)call.MethodBase).ReturnType; // Task&lt;int&gt;
  
          Task&lt;object&gt; result = Task.FromResult&lt;object&gt;(1234);
  
          // converting result to taskReturnType
          // ...
          //
  
          return result;
      }
  }
  </code></pre>
  
  <p>I found one solution but it is quite expensive:</p>
  
  <pre><code>Task AsyncMethod2(IMethodCallMessage call, MethodInfo method)
  {
      PropertyInfo resultProp = method.ReturnType.GetProperty("Result");
      Type taskResultType = resultProp.PropertyType;
      Type tcs = typeof(TaskCompletionSource&lt;&gt;);
      Type[] typeArgs = { taskResultType };
      Type genericTcs = tcs.MakeGenericType(typeArgs);
      var taskProperty = genericTcs.GetProperty("Task");
      object tcsInstance = Activator.CreateInstance(genericTcs);
      MethodInfo setResult = genericTcs.GetMethod("SetResult");
      MethodInfo setException = genericTcs.GetMethod("SetException", new Type[] { typeof(IEnumerable&lt;Exception&gt;)});
      var setEx = (Action&lt; IEnumerable&lt;Exception&gt;&gt;)setException.CreateDelegate(typeof(Action&lt;IEnumerable&lt;Exception&gt;&gt;), tcsInstance);
      Task task = (Task)taskProperty.GetValue(tcsInstance);
  
      Task&lt;object&gt; result = new Task&lt;object&gt;(delegate 
      {
          //throw new InvalidOperationException("qwerty");
          return 1234;
      });
  
      result.Start();
  
      result.ContinueWith(x =&gt;
      {
          var args = new object[] { x.Result };
          setResult.Invoke(tcsInstance, args);
      }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion);
  
      result.ContinueWith(x =&gt;
      {
          setEx(x.Exception.InnerExceptions);
      }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);
  
      return task;
  }
  </code></pre>