美文网首页
2020-09-25

2020-09-25

作者: gruan | 来源:发表于2020-09-25 15:53 被阅读0次

项目升级 (NETCore)指南

以 Ctrip.OpenService.Api 项目为例

  1. 确保安装 .NET Core 3.1
  2. 确保项目所有的依赖包都有 .NETCore 的版本。CNB.Common / CNB.DevFramework.Cache 这两个依赖包,已经支持 .NETCore
  3. 进入项目文件夹
  4. 将 Ctrip.OpenService.Api.csproj 重命名为 Ctrip.OpenService.Api.csproj_bak
  5. 用文本编辑器新建文件 Ctrip.OpenService.Api.csproj , 保存到原目录。
  6. 在新项目中, 排除 Properties/AssemblyInfo.cs
  7. Core 项目默认会把文件夹内的所有文件都包含进项目中, 要把不在TFS中的文件都删掉, 避免产生错误.
  8. 新的 csproj 文件内容及说明如下所示
<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup Label="Globals">
        <SccProjectName>SAK</SccProjectName>
        <SccProvider>SAK</SccProvider>
        <SccAuxPath>SAK</SccAuxPath>
        <SccLocalPath>SAK</SccLocalPath>
    </PropertyGroup>


    <PropertyGroup>
        <!--
        生成多个目标版本, 可以是 netstandard2.0, net45, net451, net461 等.
        提供 net452 的版本,是因为当前主项目是 net452 的,要兼容老的项目才提供这个版本的
        -->
        <TargetFrameworks>netstandard2.1;net452;</TargetFrameworks>
        <!--指定命名空间,这里是为了兼容代码,如果不设置,新添加的文件的命名空间就变了-->
        <!-- <RootNamespace>Ctrip.OpenService.Api</RootNamespace> -->
        <!--指定DLL名称,这里是为了和老的DLL兼容,DLL 就会改名了-->
        <!-- <AssemblyName>Ctrip.OpenService.Api</AssemblyName> -->

        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
        <IncludeSymbols>true</IncludeSymbols>
        <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
        <!--为false 不会生成版本信息, 注意把 Properties/AssemblyInfo.cs 文件排除-->
        <GenerateAssemblyInfo>true</GenerateAssemblyInfo>

        <!--CPS_SUP.Change, Version=0.0.0.11, Culture=neutral, PublicKeyToken=null 中的 Version-->
        <AssemblyVersion>2.0.0.0</AssemblyVersion>

        <!--无用-->
        <!--<AssemblyFileVersion>5.0.0.3</AssemblyFileVersion>-->

        <!--文件->属性->文件版本-->
        <FileVersion>2.0.0.0</FileVersion>

        <PackageTags>CNBooking</PackageTags>
        <!--NUGET 包版本-->
        <PackageVersion>2.0.0.0</PackageVersion>

        <Authors>xling</Authors>

        <LangVersion>8.0</LangVersion>
        <!--文档路径-->
        <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
    </PropertyGroup>


    <!--
    不同的 Framework 的依赖版本不一样,
    比如 StackExchange.Redis 1.2.6 以上的版本只支持 .NET 4.6.1 以上的版本,
    所以在 net451 最高能使用的版本是 1.2.6
    -->
    <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
        <PackageReference Include="CNB.Common" Version="0.0.0.45-beta" />
        <PackageReference Include="CNB.DevFrame.Cache" Version="5.0.0.5" />
        <PackageReference Include="protobuf-net" Version="2.4.0" />
        <PackageReference Include="StackExchange.Redis" Version="2.1.58" />
        <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
        <PackageReference Include="System.Net.Http" Version="4.3.4" />
    </ItemGroup>

    <!--要确保兼容包(NET452)里的依赖版本和 packages.config 里的版本是一致的 -->
    <!--如果多个版本都有相同的依赖,可以用 OR-->
    <!--<ItemGroup Condition=" '$(TargetFramework)' == 'net451' OR '$(TargetFramework)' == 'net452'">-->
    <ItemGroup Condition=" '$(TargetFramework)' == 'net452'">
        <PackageReference Include="CNB.Common" Version="0.0.0.45-beta" />
        <PackageReference Include="CNB.DevFrame.Cache" Version="5.0.0.5" />
        <PackageReference Include="protobuf-net" Version="[2.0.0.668]" />
        <PackageReference Include="StackExchange.Redis" Version="[1.2.6]" />
        <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
        <PackageReference Include="System.Net.Http" Version="4.3.4" />
    </ItemGroup>

    <!--因为上面设置了 GenerateAssemblyInfo = true, 会自动生成 AssemblyInfo , 所以这里要把 Properties\AssemblyInfo.cs 排除 -->
    <ItemGroup>
        <Compile Remove="Properties\AssemblyInfo.cs" />
    </ItemGroup>

    <!--<ItemGroup>
        <Folder Include="Properties\" />
    </ItemGroup>-->

</Project>


  1. CNB.Common 中的 RequestHelper 使用的是 HttpWebRequest, 天生存在缺陷, 不推荐在继续使用,请使用 System.Net.HttpClient 代替。

    • HttpClient 应该使用全局的, 不应该每次都新实例.
    • 使用 HttpClient 后, 是否使用代理/代理地址, 不能在动态切换, 在程序启动的时候,就必须指定.
    • HttpClient 的超时不方便调整, 但是可以按以下方法变通:
    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="opt"></param>
    public static void Init(ApiClientOption opt)
    {
        if (!Clients.ContainsKey(opt.ApiID))
        {
    
            var handler = new HttpClientHandler()
            {
                AutomaticDecompression = DecompressionMethods.GZip,
                UseProxy = opt.UseProxy,
                Proxy = !opt.UseProxy ? null : new WebProxy(opt.ProxyAddress),
            };
            var hc = new HttpClient(handler)
            {
                BaseAddress = new Uri(opt.BaseUri),
                //这里指定超时为无限, 在 BaseMethod 里的 Timeout 默认为 100 秒.
                //因为这个地方不方便自定义
                Timeout = Timeout.InfiniteTimeSpan
            };
    
            var client = new ApiClient() { Option = opt, HttpClient = hc };
            Clients.TryAdd(opt.ApiID, client);
        }
    }    
    
    ...
    ...
    public abstract class BaseMethod<T>
    {
        /// <summary>
        /// 默认 100 秒
        /// </summary>
        public int? Timeout { get; set; } = 100000;    
    
        ....
        ....
        try
        {
            using (var cts = new CancellationTokenSource())
            using (var content = new StringContent(json, Encoding.UTF8, "application/json"))
            using (var msg = new HttpRequestMessage()
            {
                Content = content,
                Method = HttpMethod.Post,
                RequestUri = new Uri(client.Option.BaseUri),
            })
            {
                if (this.Timeout > 0)
                    cts.CancelAfter(this.Timeout.Value);
    
                msg.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
    
                using (var rsp = await client.HttpClient.SendAsync(msg, cts.Token))
                {
                    if (rsp.StatusCode == HttpStatusCode.OK)
                        result = await rsp.Content.ReadAsStringAsync();
                }
    
            }
        }
        catch (TaskCanceledException e)
        {
            throw new TimeoutException("请求超时");
        }        
    
    • HttpClient.Timeout 设置为无限等待 Timeout.InfiniteTimeSpan; 使用 CancellationTokenSource (cts.CancelAfter(this.Timeout.Value)) 来控制超时时间.

相关文章

  • 需求梳理会

    时间:2020-09-25 地点:1215会议室 参会人:Scrum团队&产品负责&业务方 时长:1.5~2.5h...

  • 函数之参数详解

    函数之参数详解 2020-09-25 Reads 4 位置入参 函数调用时,实参默认按位置顺序传递,需要个数和形参...

  • 2020-09-25

    2020-09-25 【晚上好#商玉玲#20200925日精进简书第4天】印象笔记63天,总第67天 表现分:9分...

  • 【写作100天】3/100 在日常生活中修行

    2020-09-25【写作100天】3/100 在日常生活中修行 从事金融保险经纪人以来,每天都要学习大量的知识,...

  • 别让意识挡住了脚步

    我怎么如此幸运-重生28-戴红霞(2020-09-25) 我怎么如此幸运-别让意识挡住了脚步 1.我怎么如此幸运我...

  • 2020-09-26

    2020-09-25 姓名 :曹静杰 企业名称 : 辽宁辽阳丛迪服装有限公司 组别 388期 反省1组 志工529...

  • 《华与华工作法》【023】华与华改善提案制度简史(2)从个人改善

    《华与华工作法》【022】华与华改善提案制度简史(2)从个人改善提案到周改善提案2020-09-25 时间到了20...

  • 苗寨随记

    2020-09-25 西江千户苗寨客栈内 雨 贵州之行第四天,坐着大巴弯弯绕绕从荔波县城来到了西江...

  • MySQL物理备份

    2020-09-25 物理备份 直接备份数据库文件,适用于大型数据库环境,不受存储引擎的限制,但不能恢复到不同版本...

  • 2020-09-25 孩子长大了 三宝妈成长日记第57篇

    2020-09-25 星期五 晴转阴 三宝妈成长日记第57篇 三宝妈:1.早起学习财务课程,家庭保障体系,对保险有...

网友评论

      本文标题:2020-09-25

      本文链接:https://www.haomeiwen.com/subject/jsufuktx.html