public async Task <string> FillTemplateAsync <T>(T contract) where T : new() { var requestKey = ReflectionUtils.GetRequestName(contract.GetType()); var responseKey = ReflectionUtils.GetResponseName(contract.GetType()); Type requestType; ITemplateRequest <T> request; if (_requestTypes.TryGetValue(requestKey, out requestType)) { request = ReflectionUtils.InstantiateCachedRequest <T>(requestType); } else { request = ReflectionUtils.InstantiateTemplateRequest <T>(); requestType = request.GetType(); _requestTypes.Add(requestKey, requestType); } request.Variables = contract; Type responseType; if (!_responseTypes.TryGetValue(responseKey, out responseType)) { responseType = ReflectionUtils.BuildDynamicResponseType <T>(); _responseTypes.Add(responseKey, responseType); } var callRpcMethod = typeof(TemplaterService).GetMethod(nameof(CallRpc), BindingFlags.Instance | BindingFlags.NonPublic); var callRpcGeneric = callRpcMethod.MakeGenericMethod(requestType, responseType, contract.GetType()); var task = (Task <ITemplateResponse <T> >)callRpcGeneric.Invoke(this, new object[] { request }); var response = await task; return(response.Text); }