【问题标题】:C#- return IEnumerable<object> on task async callC#- 在任务异步调用上返回 IEnumerable<object>
【发布时间】:2019-08-17 04:45:00
【问题描述】:

我有以下代码:

public class TardiisServiceAsync
{
    private static TardiisServiceAsync instance;

    public static TardiisServiceAsync Instance
    {
        //Singleton
        get
        {
            if (instance == null)
            {
                instance = new TardiisServiceAsync();
            }
            return instance;
        }
    }
    public const string CACHE_PREFIX_TARDIIS_SERVICE = "TardiisServiceAsync_";
    public static Dictionary<string, Tuple<string, object>> clients = new Dictionary<string, Tuple<string, object>>();
    public delegate Task<IEnumerable<object>> GetServiceList(object client, string connectionId, TardiisServiceParameters parameters = null);


    public async Task<IEnumerable<object>> GetDemographicGroupsDelegateAsync(object client, string connectionId, TardiisServiceParameters parameters = null)
    {
        //Returns IEnumerable<object> task
        var test = Convert(client.GetType().GetMethod("GetDemographicGroupsAsync").Invoke(client, new object[] { connectionId }));
        var result = await test;
        return (IEnumerable<object>)result;
    }

    public async Task<IdNameObject[]> GetDemographicGroupsAsync()
    {
        //This task is called from hight level class
        Task<IdNameObject[]> cacheValue = null;
        string cacheKey = CACHE_PREFIX_TARDIIS_SERVICE + Membership.GetUser().UserName + "GetDemographicGroupsAsync" + GetMarketCode();

        if (ConfigurationManager.AppSettings[ConstantsHelper.FIELD_CONFIG_USE_CACHE_KEY] != null && bool.Parse(ConfigurationManager.AppSettings[ConstantsHelper.FIELD_CONFIG_USE_CACHE_KEY]))
        {
            if (HttpContext.Current.Cache[cacheKey] == null)
            {
                var taskResult = InitializeTardiisInstanceAndCallService(GetDemographicGroupsDelegateAsync);
                var test = await taskResult;
                cacheValue = (Task<IdNameObject[]>)HttpContext.Current.Cache[cacheKey];//This is not implemented yet
            } 
        }

        return await cacheValue;
    }

    public static Task<T> Convert<T>(T value)
    {
        return Task.FromResult<T>(value);
    }

    public static EnumHelper.EnumMarketCode GetMarketCode(EnumHelper.EnumMarketCode? marketCode = null)
    {
        //Returns market code
        if (!marketCode.HasValue)
            return (EnumHelper.EnumMarketCode.US);
        else
            return marketCode.Value;
    }

    private Task<IEnumerable<object>> InitializeTardiisInstanceAndCallService(GetServiceList getServiceList, TardiisServiceParameters parameters = null, EnumHelper.EnumMarketCode? marketCode = null, bool creatingConnectionsForAllCountries = false, string username = "")
    {
        //Get the instance and call the tardiis correct tardiis service depends on the market code
        marketCode = GetMarketCode(marketCode);
        MembershipUser membershipUser = Membership.GetUser();
        string currentUsername = (membershipUser != null ? membershipUser.UserName : username);
        string currentKey = currentUsername + "_" + marketCode;

        if (clients.ContainsKey(currentKey))
        {
            try
            {
                //check if the connection is still active, or we should reconnect.
                return getServiceList(clients[currentKey].Item2, clients[currentKey].Item1, parameters);
            }
            catch (Exception) { }
        }
        //At this point there is no connection, we need to open it.                            
        object client = TardiisServiceFactory.GetService(marketCode.Value);

        UserDTO userDTO = UserService.Instance.GetByUsername(currentUsername);
        TardiisUserDTO tardiisUserDTO = UserService.Instance.GetTardiisUserByUserIdAndMarketCode(userDTO.ID, marketCode.Value.ToString());

        if (tardiisUserDTO.TardiisUsername == null)
        {
            if (creatingConnectionsForAllCountries)
                return null;
            else
                throw new TardiisLoginException("Please enter your credentials");
        }

        object user = TardiisServiceFactory.GetUser(marketCode.Value, tardiisUserDTO.TardiisUsername, tardiisUserDTO.TardiisPassword);
        string connectionId;
        try
        {
            connectionId = (string)client.GetType().GetMethod("InitConnection").Invoke(client, new object[] { user });
        }
        catch (FaultException ex)
        {
            // This exception is catched globally by BaseController and prompts the user to enter his
            // tardiis credentials again
            throw new TardiisLoginException(ex.InnerException.Message, ex);
        }
        catch (TargetInvocationException ex)
        {
            // This exception is catched globally by BaseController and prompts the user to enter his
            // tardiis credentials again
            throw new TardiisLoginException(ex.InnerException.Message, ex);
        }

        clients[currentKey] = new Tuple<string, object>(connectionId, client);
        return getServiceList(clients[currentKey].Item2, clients[currentKey].Item1, parameters);
    }

    private void AddToCache(string key, object value)
    {
        HttpContext.Current.Cache.Add(key, value, null, DateTime.Now.AddMinutes(30), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
    }

}

我收到以下错误消息:

无法将“System.Threading.Tasks.Task[System.Object]”类型的对象转换为“System.Collections.Generic.IEnumerable1[System.Object]”类型。

任务的结果是TypedClass[]

如何在调用方法上以Task&lt;IEnumerable&lt;object&gt;&gt; 的形式返回。

这是另一个具有相似逻辑但以同步方式的类的“副本”。这个想法是改变一些方法 所以它们可以同步运行。

谢谢!

【问题讨论】:

  • var taskResult = task.Result;当您添加 .result 时,这不是一项任务,它将是您使用的可枚举或其他类型
  • 嗨@Pliskin,感谢您的回复,我明白这一点,但我无法将Task&lt;MyCustomClass&gt; 结果转换为Task&lt;IEnumerable&lt;object&gt;&gt;。谢谢。
  • taskResult的类型和convert方法的param类型是什么?
  • 结果是Task&lt;TardiisPlanning.TardiisPlanningService.DemographicGroup[]&gt;一个自定义类数组。下面我留下 Convert 方法的代码:public static Task&lt;T&gt; Convert&lt;T&gt;(T value) { return Task.FromResult&lt;T&gt;(value); }
  • 检查更新的代码,让我知道它是否有效,或者将其添加为 Convert resultado.ToList() 的参数

标签: c# asynchronous task


【解决方案1】:
    public async Task<IEnumerable<object>> GetDemographicGroupsDelegateAsync(object client, string connectionId, TardiisServiceParameters parameters = null)
{

    var test = Convert(client.GetType().GetMethod("GetDemographicGroupsAsync").Invoke(client, new object[] { connectionId }));
    var result = await test;
    var resultado = test.Result;
    return Convert(new List<Object>{resultado});
}

【讨论】:

    【解决方案2】:

    如果您有 IEnumerable&lt;A&gt; 之类的数组,您可以使用 Linq-Methode Cast&lt;object&gt;() 将其转换为 IEnumerable&lt;object&gt;

    public async Task<IEnumerable<object>> GetDemographicGroupsDelegateAsync(object client, string connectionId, TardiisServiceParameters parameters = null)
    {
    
        var test = Convert(client.GetType().GetMethod("GetDemographicGroupsAsync").Invoke(client, new object[] { connectionId }));
        var task = await test;
        var taskResult = await task;
        return taskResult.Cast<object>();
    }
    

    【讨论】:

    • 嗨,Ackdari,谢谢,但变量 taskResullt 是一个对象类型,不是 awatiable,我说的对吗?
    • @MarceloArias 好吧,我不知道你的对象是什么类型的?如果您告诉我test 的类型和task 的类型是什么,我可能会澄清我的答案。
    猜你喜欢
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 2013-04-16
    • 2019-01-10
    相关资源
    最近更新 更多