• c# 泛型的应用


    泛型静态类 & function作为参数

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="OD">original datas type:get from proxy api</typeparam>
        /// <typeparam name="SD">save datas type</typeparam>
        public static class ReportOperation<OD,SD> where OD : class where SD : class 
        {
            static int _syncCallApiMaxNum= ConfigHelper.SyncCallApiMaxNum;
            static int _MaxSaveDataNum = ConfigHelper.MaxSaveDataNum;
            static string OriginalDatasType = typeof(OD).FullName;
            static string SaveDatasType = typeof(SD).FullName;
    
            private static bool TaskSplitForSave(List<ReportSaveTask<SD>> taskList, ILogBase _logger)
            {
                bool saveResult = true;
                try
                {
                    _logger.Info($"TaskSplitForSave.SaveDatasType:{SaveDatasType};");
                    if (taskList == null || taskList.Count() == 0)
                    {
                        return false;
                    }
                    int index = 0;
                    int sumNum = taskList.Count();
                    int syncCallApiNum = sumNum > 0 ? _syncCallApiMaxNum : sumNum;
                    while (index < sumNum)
                    {
                        List<ReportSaveTask<SD>> temp = new List<ReportSaveTask<SD>>();
                        syncCallApiNum = syncCallApiNum > sumNum - index ? sumNum - index : syncCallApiNum;
                        temp = taskList.GetRange(index, syncCallApiNum);
                        index = index + syncCallApiNum;
                        System.Threading.Thread.Sleep(5000);
                        foreach (var oneT in temp)
                        {
                            _logger.Info($"start save Report datas to database. start:{index},num:{syncCallApiNum},request:{JsonConvert.SerializeObject(oneT.Data)}");
                            oneT.SaveResult.Start();
                        }
                        Task.WaitAll(temp.Select(each => each.SaveResult).ToArray());
                        foreach (var teskOne in temp)
                        {
                            var saveTempResult = teskOne.SaveResult.Result;
                            saveResult = saveResult && saveTempResult;
    
                            if (!saveTempResult)
                            {
                                _logger.Warn($"failed to async Report datas to database!,request:{JsonConvert.SerializeObject(teskOne.Data)}");
                            }
                            else
                            {
                                _logger.Info($"report datas to DB successed!,request:{JsonConvert.SerializeObject(teskOne.Data)}");
                            }
                        }
                    }
                    _logger.Info($"TaskSplitForSave result:{JsonConvert.SerializeObject(saveResult)};");
                    return saveResult;
                }
                catch (Exception ex)
                {
                    _logger.Error($"ProxyReportCallSplit:{ex.ToString()}");
                    throw ex;
                }
            }
    
    
            private static List<ReportSaveTask<SD>> DataSplitForSave(List<SD> reportDB,Func<List<SD>,bool> saveOperate, ILogBase _logger)
            {
                
                List<ReportSaveTask<SD>> taskList = new List<ReportSaveTask<SD>>();
                try
                {
                    _logger.Info($"DataSplitForSave request.reportDB:{JsonConvert.SerializeObject(reportDB)};");
                    if (reportDB == null || reportDB.Count() == 0)
                    {
                        return null;
                    }
    
                    int index = 0;
                    int sumNum = reportDB.Count();
                    int eachInsert = sumNum > 0 ? _MaxSaveDataNum : sumNum;
                    while (index < sumNum)
                    {
                        List<SD> temp = new List<SD>();
                        eachInsert = eachInsert > sumNum - index ? sumNum - index : eachInsert;
                        temp = reportDB.GetRange(index, eachInsert);
                        index = index + eachInsert;
                        var taskTemp = new Task<bool>(()=>saveOperate(temp));//_FacebookReportClient.Save(temp)
                        taskList.Add(new ReportSaveTask<SD>() { SaveResult = taskTemp, Data = temp });
                    }
                    return taskList;
                }
                catch (Exception ex)
                {
                    _logger.Error($"save datas to DB error:{ex.ToString()},request:{JsonConvert.SerializeObject(reportDB)}");
                    throw ex;
                }
            }
    
            public static bool ProxyApiSplitToCall(List<Task<List<OD>>> taskList,Func<List<OD>,List<SD>> DateConvertToDB, Func<List<SD>,bool> saveOperate, ILogBase _logger)
            {
                bool result = true;
                try
                {
                    _logger.Info($"ProxyApiSplitToCall");
                    if (taskList == null || taskList.Count() == 0)
                    {
                        return false;
                    }
                    int index = 0;
                    int sumNum = taskList.Count();
                    int syncCallApiNum = sumNum > 0 ? _syncCallApiMaxNum : sumNum;
                    while (index < sumNum)
                    {
                        syncCallApiNum = syncCallApiNum > sumNum - index ? sumNum - index : syncCallApiNum;
                        List<Task<List<OD>>> temp = taskList.GetRange(index, syncCallApiNum);
                        index = index + syncCallApiNum;
    
                        System.Threading.Thread.Sleep(5000);
                        foreach (var oneT in temp)
                        {
                            oneT.Start();
                        }
                        Task.WaitAll(temp.ToArray());
    
                        #region save data
                        List<OD> allReports = new List<OD>();
                        CommandHelper.UnionAllTaskResult<OD>(temp, ref allReports);
                        if (allReports == null || allReports.Count() == 0)
                        {
                            _logger.Warn($"no datas can get from proxy call![{JsonConvert.SerializeObject(allReports)}]");
                            continue;
                        }
                        _logger.Info($"datas get from proxy call:{JsonConvert.SerializeObject(allReports)}");
                        List<SD> reportDB = DateConvertToDB(allReports);
                        if (reportDB == null || reportDB.Count() == 0)
                        {
                            _logger.Warn($"no datas need to be created or updated:{JsonConvert.SerializeObject(reportDB)}");
                            continue;
                        }
                        _logger.Info($"datas need to be save :{JsonConvert.SerializeObject(reportDB)}");
                        List<ReportSaveTask<SD>> DataSaveT= DataSplitForSave(reportDB, saveOperate, _logger);
                        bool saveResult = TaskSplitForSave(DataSaveT, _logger);
                        _logger.Info($"datas save result:{JsonConvert.SerializeObject(saveResult)}");
                        #endregion
    
                        result = result & saveResult;
                    }
                    return result;
                }
                catch (Exception ex)
                {
                    _logger.Error($"ProxyReportCallSplit:{ex.ToString()}");
                    throw ex;
                }
            }
        }
    

      

    静态类的使用

    bool saveResult = ReportOperation<FacebookDailyReportConvertFromClient, FacebookImpressDeviceReport>.ProxyApiSplitToCall(taskList, dataConvertFunc, dataSaveFunc, _logger);
    

      

    function作为参数的使用

                    Func<List<FacebookDailyReportConvertFromClient>, List<FacebookImpressDeviceReport>> dataConvertFunc = (originalData) => { return DateConvertToDB(originalData, accounts); };
                    Func<List<FacebookImpressDeviceReport>, bool> dataSaveFunc = (saveDB) => { return SaveReportsToDB(saveDB); };
                    bool saveResult = ReportOperation<FacebookDailyReportConvertFromClient, FacebookImpressDeviceReport>.ProxyApiSplitToCall(taskList, dataConvertFunc, dataSaveFunc, _logger);
    

      

    泛型抽象类:

        /// <summary>
        /// get reoports from proxy client 
        /// </summary>
        /// <typeparam name="RQ">request type</typeparam>
        /// <typeparam name="RP">response list type</typeparam>
        /// <typeparam name="CRQ">proxy client request type</typeparam>
        /// <typeparam name="CRP">proxy client response type</typeparam>
        public abstract class ReportDownloadBase<RQ, RP,CRQ,CRP> where RQ : class where RP : class where CRQ : class where CRP : class
        {
            protected string exportPath;
            protected System.Collections.Specialized.NameValueCollection appSettings;
            protected ILogBase _logger;
            protected string _plantform;
    
            public ReportDownloadBase(ILogBase logger,string plantform)
            {
                _plantform = plantform;
                appSettings = WestWin.Common.Configuration.ConfigurationManager.Default.AppSettings;
                exportPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), appSettings["ReportRawPath"], plantform);
                _logger = logger;
            }
    
            /// <summary>
            /// Generate ReportRequest for proxy client
            /// </summary>
            /// <param name="req">request</param>
            /// <returns></returns>
            protected abstract CRQ GenerateReportRequest(RQ req);
    
            /// <summary>
            /// Generate Results to return 
            /// </summary>
            /// <param name="resp">ReportResponse</param>
            /// <param name="breakdownValue">breakdownValue </param>
            /// <returns>result list</returns>
            protected abstract List<RP> GenerateResultsByReportResponse(CRP resp, RQ req);
    
            /// <summary>
            /// get client response from client request
            /// </summary>
            /// <param name="req"></param>
            /// <returns></returns>
            protected abstract CRP GetResponseFromRequest(CRQ req);
    
            /// <summary>
            /// Get Results By Request
            /// </summary>
            /// <param name="request"></param>
            /// <param name="breakdownValue"></param>
            /// <returns></returns>
            protected List<RP> Process(RQ request,string breakdownValue)
            {
                try
                {
                _logger.Info($"{_plantform} GetReport request:{JsonConvert.SerializeObject(request)}");
                var req = GenerateReportRequest(request);
                _logger.Info($"{_plantform} proxy client request:{JsonConvert.SerializeObject(req)}");         
                
                    CRP response = null;
                    int maxTry = ConfigHelper.ApiTryMaxNum;
                    int count = 0;
                    while (count < maxTry)
                    {
                        count++;
                        response = null;
                        try
                        {
                            response = GetResponseFromRequest(req);
                        }
                        catch (Exception e)
                        {
                            _logger.Error($"{_plantform} proxy client get report failed:Round {count}", e);
                            if(count== maxTry)
                            {
                                _logger.Error($"{_plantform} proxy client get report: exception & retry time:{count}", e);
                                throw e;
                            }
                        }
                        if (response != null) break;
                        _logger.Warn($"{_plantform} proxy client get report failed:retry Num: {count},request:{JsonConvert.SerializeObject(req)}");
                        System.Threading.Thread.Sleep(5000);
                        
                    }
                    if (response == null)
                    {
                        return null;
                    }
                   
                    _logger.Info($"{_plantform} proxy client Get Report sucess:{JsonConvert.SerializeObject(response)}");
                    var result = GenerateResultsByReportResponse(response, request);
                    _logger.Info($"{_plantform} return Report result:{JsonConvert.SerializeObject(result)}");
                    CommandHelper.CreateDictionaryIfNotExists(exportPath);
                    if (result == null || result.Count == 0)
                    {
                        _logger.Warn($"{_plantform} return empty result for request:{JsonConvert.SerializeObject(req)}");
                    }
                    else
                    {
                        var path = Path.Combine(exportPath, $"{_plantform}-row-{breakdownValue}-{DateTime.Now.ToString("yyyyMMddHHmmss")}-{Guid.NewGuid().ToString()}.csv");
                        bool saveSucess = CommandHelper.SaveDataToCSVFile<RP>(result, path);
                        _logger.Info($"{_plantform} report save local file result:{saveSucess}");
                    }
                    return result;
                }
                catch (Exception ex)
                {
                    _logger.Error($"exception. request.request: {JsonConvert.SerializeObject(request)};  request.breakdownValue: {JsonConvert.SerializeObject(breakdownValue)};error:{ex.ToString()}");
                    throw ex;
                }
            }  
        }
    

      

    被使用:

        public class FacebookCountryCmd : ReportDownloadBase<FacebookDailyReportEachRequest, FacebookDailyReportConvertFromClient, FacebookGetAdsInsightRequest, FacebookGetAdsInsightsResponse>, IFacebookCountryCmd
        {
            IFacebookCountryReportService _facebookCountryReportService;
            IFacebookProxyService _FacebookProxyClient;
            IAccountCampaignOperation _campaignOperation;
            IFacebookCampaignHelper _facebookCampaignHelper;
            Platform.Service.Enterprise.AccountChannel _accountChannel = Platform.Service.Enterprise.AccountChannel.Facebook;
            Dictionary<string, FacebookSearchAdgeolocationEntity> _countryDic=new Dictionary<string, FacebookSearchAdgeolocationEntity>();
            public FacebookCountryCmd(ILogBase logger, 
                IFacebookCountryReportService facebookCountryReportService, IAccountCampaignOperation campaignOperation, 
                IFacebookProxyService FacebookProxyClient,IFacebookCampaignHelper facebookCampaignHelper) : base(logger, "facebook")
            {
                _facebookCountryReportService = facebookCountryReportService;
                _FacebookProxyClient = FacebookProxyClient;
                _campaignOperation = campaignOperation;
                _facebookCampaignHelper = facebookCampaignHelper;
                GetAllCountry();
            }
    
            public List<FacebookCountryReport> DateConvertToDB(List<FacebookDailyReportConvertFromClient> reportDatas, List<BusinessAdsPlatformAccountDetail> accounts)
            {
                //*****
            }
    
            public void Execute(FacebookCmdOptions opt)
            {
                //*****
            }
    
    
            public bool SaveReportsToDB(List<FacebookCountryReport> reportDB)
            {
                //****
            }
    
            protected override FacebookGetAdsInsightRequest GenerateReportRequest(FacebookDailyReportEachRequest req)
            {
                //****
            }
    
            protected override List<FacebookDailyReportConvertFromClient> GenerateResultsByReportResponse(FacebookGetAdsInsightsResponse response, FacebookDailyReportEachRequest req)
            {
               //***
            }
    
            protected override FacebookGetAdsInsightsResponse GetResponseFromRequest(FacebookGetAdsInsightRequest req)
            {
                //****
            }
    
    
            private bool IfNextPage(FacebookGetAdsInsightsResponse response, ref FacebookGetAdsInsightRequest request)
            {
                //****
            }
        }
    

      

        public interface IFacebookCountryCmd: IReportCmdBase<FacebookCountryReport, FacebookCmdOptions, FacebookDailyReportConvertFromClient>
        {
        }
    

      

        /// <summary>
        /// execute download report
        /// </summary>
        /// <typeparam name="RDB">report type define by DB</typeparam>
        /// <typeparam name="CMD">command type</typeparam>
        /// <typeparam name="RP">report response including all data get from proxy client</typeparam>
        public interface IReportCmdBase<RDB,CMD,RP> where RDB : class where CMD:class where RP:class
        {
    
            /// <summary>
            /// Save Reports To DB
            /// </summary>
            /// <param name="reportDB"></param>
            /// <returns></returns>
            bool SaveReportsToDB(List<RDB> reportDB);
    
            /// <summary>
            /// convert report to match datebase define
            /// </summary>
            /// <param name="reportDatas"></param>
            /// <returns></returns>
            List<RDB> DateConvertToDB(List<RP> reportDatas, List<BusinessAdsPlatformAccountDetail> accounts);
    
            /// <summary>
            /// Execute Download Report :get from proxy client api & save original data to local file & save to DB
            /// </summary>
            /// <param name="opt">command</param>
            void Execute(CMD opt);
        }
    

      

  • 相关阅读:
    第一个WPF
    redis pub/sub 发布订阅
    php中header函数后是否应该有exit
    redis的图形界面管理工具
    redis key和value数据类型
    螺旋式打印一个二维数组
    jquery 提示插件 cluetip
    php异常处理
    ruby Methods, Procs, Lambdas, and Closures
    ruby迭代器iterator和枚举器Enumerator
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/9107493.html
Copyright © 2020-2023  润新知