標籤: 網站設計

  • 高雄鼓勵換電動機車 最高補助額達 2.3 萬

    高雄市機車總數達 201 萬輛,成為都市的污染源之一,為了鼓勵機車族更換電動機車,高雄市政府環保局推動補助政策,換車最高可獲得 2.3 萬元的補助。   高雄市政府環境保護局空噪科長鄭嵐 26 日下午表示,根據交通部機動車輛統計資料,高雄市截至 103 年 12 月底掛牌的使用中機車,總數約 201 萬輛,為鼓勵民眾汰舊換購電動車輛,高雄市環保局持續推動淘汰補助方案,除了經濟部工業局補助純購電動機車,機車族可獲得補助 7,200 元到 10,000 元外,若搭配汰舊二行程機車,再加碼補助至 17,400 元到 23,000 元。   他表示,同時,為了提升友善充電環境,高雄環保局近年來也積極推動充電站架設,除了原有公用及私有充電站,103 年完成社區大樓與電動機車經銷商等 25 座,共有充電站 217 站,讓高雄市騎乘電動車市民處處皆有電可充,建構低碳生活圈。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • 新能源汽車入北京 改為備案制

    在中國的全球新能源汽車大會上,北京市科委新能源與新材料處處長許心超透露,北京市新能源汽車準入方式有所調整,由先前的新能源汽車目錄方式改為備案方式,車型只要備案即可在北京銷售、上牌。   先前規定,按照《北京市示範應用新能源小客車生企業及品目錄》,北京市共有 7 款新能源汽車可在備案之後直接銷售、上牌。而這次許心超表示,按照中央的要求,準入方式也在改變,主要採取備案制,只要備案了就可銷售,政府則加強事後監管。
    這意味著所有中國純電動汽車都可以進京銷售、上牌,享受財政補貼,而不再像以前必須要先進入嚴格的北京市新能源汽車目錄。   另一方面,為了讓純電動汽車的使用者迅速找到充電樁,相關部門也在進行改進,一是和百度合作,標注所有充電樁的電子地圖將很快上線;二是印製北京充電樁地圖;三是辦充電體驗周活動,在 2 月 2 日至 6 日,將分 2 次聯合所有北京的汽車企業,做充電實際體驗。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※回頭車貨運收費標準

  • 發展電動車 梅克爾盼德國2030年前設百萬充電站

    摘錄自2019年11月3日中央通訊社德國報導

    德國總理梅克爾4日將與本國汽車工業代表會商,討論如何加速發展低碳排的電池驅動交通工具。她3日透過影片表示,德國在2030年前應設置100萬座電動車充電站。

    德國境內目前僅有約2萬座電動車公共充電站。梅克爾指出:「為達此(發展電動車)目的,我們想在2030年前設置100萬座充電站,而產業界將必須加入相關計畫。我們要談的就是這個。」

    路透社報導,預定明天在總理府舉行的會議,將是為相關議題舉辦的第二場,涉及儘速採取行動,以期交通運輸產業為德國達成國家碳排減量目標做出貢獻。會議將聚焦於汽油和柴油的替代方案,其中包括氫燃料和電池,以及政府和業界如何分攤給予消費者的補助,以刺激相關產品買氣。

    梅克爾表示,政府也將致力於保障就業機會。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • 「寂靜的春天」預言實現了 研究發現新菸鹼類影響水生物和魚群

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※回頭車貨運收費標準

  • 無人駕駛電動車?傳蘋果正在研發車類產品

    無人駕駛電動車?傳蘋果正在研發車類產品

      據知情人士透露,蘋果公司早在一年前就成立了汽車研發團隊,目前該團隊共有 100 多名員工,正在研發一款代號為 Titan 的電動車,同時蘋果公司與汽車產業中無人駕駛方面的資深人士互動頻繁,研發方向很有可能是一款無人駕駛的電動車。   蘋果公司對於汽車類產品和服務的研發計劃不僅僅局限在軟體系統,而是以打造整車為目標。在研發方面蘋果並沒有與傳統汽車廠商建立太多聯繫,據知情人士透露蘋果正在與汽車零組件廠商諮詢,主要是電力和車聯網方面的公司,這些諮詢並沒有涉及合作的部分。   蘋果公司已經招募了不少汽車產業的資深人士,包括前 Benz 北美研發中心的總裁 Johann Jungwirth,他在 2014 年 9 月加入蘋果四,此前曾負責 Benz 的自動駕駛、用戶界面設計、產品風格設計等工作。     本文全文授權轉載自《科技新報》─〈〉

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • 挖角鋰電池廠 A123 傳蘋果電動車將於 2020 年量產

    過去幾個月來,蘋果打算進軍終極行動裝置──汽車的傳言甚囂塵上。最新消息更顯示,蘋果正在加緊鞭策研發團隊,希望能在 2020 年產出旗下第一輛電動車。無獨有偶,數小時前才剛洩漏的法院文件顯示,美國汽車鋰離子電池與電池系統廠商 A123 Systems Inc. 控訴蘋果挖角多名重要的工程師,或許蘋果開發電動車是真有其事。   彭博社 20 日引述未具名消息人士報導,蘋果最快 2020 年就會開始量產電動車。一般來說,有經驗的汽車業者想要研發一款全新汽車、通常得花上 5 至 7 年的時間,假如要從零開始、時間更得費上 10 年之久。蘋果設定了如此緊迫的量產時程,凸顯了該公司對汽車領域的強大企圖心。   相較之下,特斯拉(Tesla Motors Inc.)、通用汽車(General Motors Co.)這兩家汽車大廠,則都預定要在 2017 年發表一輛單次充電後可行駛超過 200 英里、售價低於 4 萬美元的電動車。   蘋果的汽車團隊過去幾個月加緊聘人、目前已有 200 人之譜,而最新延攬的員工大多是電池、機器人專才。不過,根據消息人士的說法,倘若汽車的進展不如預期,蘋果仍可能推延開發案、或甚至直接抽手退出。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※回頭車貨運收費標準

  • 使用 nuget server 的 API 來實現搜索安裝 nuget 包

    使用 nuget server 的 API 來實現搜索安裝 nuget 包

    使用 nuget server 的 API 來實現搜索安裝 nuget 包

    Intro

    nuget 現在幾乎是 dotnet 開發不可缺少的一部分了,還沒有用過 nuget 的就有點落後時代了,還不快用起來

    nuget 是 dotnet 里的包管理機制,類似於前端的 npm ,php 的 composer,java 里的 maven …

    nuget 定義了一套關於 nuget server 的規範,使得用戶可以自己實現一個 nuget server

    也正是這些規範,使得我們可以根據這些規範來實現 nuget server 的包管理的功能,今天主要介紹一下,根據 nuget server 的 api 規範使用原始的 HTTP 請求來實現 nuget 包的搜索和使用 nuget 提供的客戶端 SDK 來實現 nuget 包的搜索和下載

    Nuget Server Api

    Nuget 協議介紹

    nuget 的協議有好幾個版本,目前主要用的是 v3,開源的 nuget server Baget 也實現了基於 nuget protocal v3 的規範

    我們添加 nuget 源的時候會指定一個 source url,類似 https://api.nuget.org/v3/index.json 這樣的,着通常被稱為 Service Index,是一個 nuget 源的入口,有點類似於 Identity Server 里的發現文檔,通過這個地址可以獲取到一系列的資源的地址

    有一些資源是協議規範里定義的必須要實現的,有一些是可選的,具體參考官方文檔,以後隨着版本變化,可能會有差異,目前 nuget.org 提供的資源如下:

    Nuget.org 提供了兩種搜索的方式,

    一個是 SearchQuery,會根據包名稱、 tag、description 等信息去匹配關鍵詞,

    一個是 SearchAutocomplete 根據包名稱的前綴去匹配包的名稱

    獲取某個 nuget 包的版本信息,可以使用 PackageBaseAddress 來獲取

    ServiceIndex 返回的信息示例如下:

    返回的信息會有一個 resources 的數組,會包含各種不同類型的資源,對應的 @id 就是調用這種類型的API要用到的地址,下面來看一個搜索的示例

    在每個 API 的文檔頁面可以看到會使用的 @type,調用這個 API 的時候應該使用這些 @type 對應的資源

    這裏的 @id 就是上面的 resource 對應的 @id

    參數說明:

    q 搜索時所用的關鍵詞,

    skip/take 用來分頁显示查詢結果,

    prelease 用來指定是否限制預覽版的 package,true 包含預覽版的 nuget 包,false 只包含已經正式發布的 nuget 包

    semVerLevel 是用來指定包的語義版本

    The semVerLevel query parameter is used to opt-in to SemVer 2.0.0 packages. If this query parameter is excluded, only packages with SemVer 1.0.0 compatible versions will be returned (with the standard NuGet versioning caveats, such as version strings with 4 integer pieces). If semVerLevel=2.0.0 is provided, both SemVer 1.0.0 and SemVer 2.0.0 compatible packages will be returned. See the SemVer 2.0.0 support for nuget.org for more information

    packageType 用來指定 nuget 包的類型,目前支持的類型包括 Dependency(默認)項目依賴項,DotnetTool(dotnetcore 2.1 引入的 dotnet cli tool),Template (dotnet new 用) 自定義的項目模板

    其他的 API 可以自行參考官方文檔:https://docs.microsoft.com/en-us/nuget/api/service-index

    Packages

    SearchQuery 返回的信息比較多而且可能並不準確,適用於不清楚包的名稱的時候使用,如果知道 nuget 包的名稱(PackageId) ,可以使用 SearchAutocomplete 來搜索,這樣更精準,返回的信息也更簡單,只有匹配的 package 名稱

    通過原始 api 調用的方式實現 nuget 包的搜索

    using var httpClient = new HttpClient(new NoProxyHttpClientHandler());
    // loadServiceIndex
    var serviceIndexResponse = await httpClient.GetStringAsync(NugetServiceIndex);
    var serviceIndexObject = JObject.Parse(serviceIndexResponse);
    
    var keyword = "weihanli";
    
    //https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource
    var queryEndpoint = serviceIndexObject["resources"]
        .First(x => x["@type"].Value<string>() == "SearchQueryService")["@id"]
        .Value<string>();
    var queryUrl = $"{queryEndpoint}?q={keyword}&skip=0&take=5&prerelease=false&semVerLevel=2.0.0";
    var queryResponse = await httpClient.GetStringAsync(queryUrl);
    Console.WriteLine($"formatted queryResponse:");
    Console.WriteLine($"{JObject.Parse(queryResponse).ToString(Formatting.Indented)}");
    
    // https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource
    var autoCompleteQueryEndpoint = serviceIndexObject["resources"]
        .First(x => x["@type"].Value<string>() == "SearchAutocompleteService")["@id"]
        .Value<string>();
    var autoCompleteQueryUrl = $"{autoCompleteQueryEndpoint}?q={keyword}&skip=0&take=5&prerelease=false&semVerLevel=2.0.0";
    var autoCompleteQueryResponse = await httpClient.GetStringAsync(autoCompleteQueryUrl);
    Console.WriteLine($"formatted autoCompleteQueryResponse:");
    Console.WriteLine($"{JObject.Parse(autoCompleteQueryResponse).ToString(Formatting.Indented)}");
    
    

    output 示例:

    Query 返回示例

    Autocomplete 返回結果

    從上面我們可以看到 Query 接口返回了很多的信息,Autocomplete 接口只返回了 package 的名稱,返回的信息更為簡潔,所以如果可以使用 Autocomplete 的方式就盡可能使用 Autocomplete 的方式

    Package Versions

    前面我們提到了可以使用 PackageBaseAddress 來查詢某個 nuget 包的版本信息,文檔地址:https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource,來看一下示例:

    using (var httpClient = new HttpClient(new NoProxyHttpClientHandler()))
    {
        // loadServiceIndex
        var serviceIndexResponse = await httpClient.GetStringAsync(NugetServiceIndex);
        var serviceIndexObject = JObject.Parse(serviceIndexResponse);
    
        // https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource
        var packageVersionsEndpoint = serviceIndexObject["resources"]
            .First(x => x["@type"].Value<string>() == "PackageBaseAddress/3.0.0")["@id"]
            .Value<string>();
    
        var packageVersionsQueryUrl = $"{packageVersionsEndpoint}/dbtool.core/index.json";
        var packageVersionsQueryResponse = await httpClient.GetStringAsync(packageVersionsQueryUrl);
        Console.WriteLine("DbTool.Core versions:");
        Console.WriteLine(JObject.Parse(packageVersionsQueryResponse)
                          .ToString(Formatting.Indented));
    }
    

    output 示例:

    注:api 地址中的 packageId 要轉小寫

    Nuget Client SDK

    除了上面的根據 api 自己調用,我們還可以使用 nuget 提供的客戶端 sdk 實現上述功能,這裏就不詳細介紹了,有需要可能查閱官方文檔:https://docs.microsoft.com/en-us/nuget/reference/nuget-client-sdk

    下面給出一個使用示例:

    var packageId = "WeihanLi.Common";
    var packageVersion = new NuGetVersion("1.0.38");
    
    var logger = NullLogger.Instance;
    var cache = new SourceCacheContext();
    // 在 SDK 的概念里,每一個 nuget 源是一個 repository
    var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
    
    // SearchQuery
    {
        var resource = await repository.GetResourceAsync<PackageSearchResource>();
        var searchFilter = new SearchFilter(includePrerelease: false);
    
        var results = await resource.SearchAsync(
            "weihanli",
            searchFilter,
            skip: 0,
            take: 20,
            logger,
            CancellationToken.None);
        foreach (var result in results)
        {
            Console.WriteLine($"Found package {result.Identity.Id} {result.Identity.Version}");
        }
    }
    // SearchAutoComplete
    {
        var autoCompleteResource = await repository.GetResourceAsync<AutoCompleteResource>();
        var packages =
            await autoCompleteResource.IdStartsWith("WeihanLi", false, logger, CancellationToken.None);
        foreach (var package in packages)
        {
            Console.WriteLine($"Found Package {package}");
        }
    }
    //
    {
        // get package versions
        var findPackageByIdResource = await repository.GetResourceAsync<FindPackageByIdResource>();
        var versions = await findPackageByIdResource.GetAllVersionsAsync(
            packageId,
            cache,
            logger,
            CancellationToken.None);
    
        foreach (var version in versions)
        {
            Console.WriteLine($"Found version {version}");
        }
    }
    

    More

    你可以使用 nuget sdk 方便的實現 nuget 包的下載安裝,內部實現了簽名校驗等,這樣就可以把本地不存在的 nuget 包下載到本地了,

    實現示例:

    {
        var pkgDownloadContext = new PackageDownloadContext(cache);
        var downloadRes = await repository.GetResourceAsync<DownloadResource>();
    
        var downloadResult = await RetryHelper.TryInvokeAsync(async () =>
            await downloadRes.GetDownloadResourceResultAsync(
                new PackageIdentity(packageId, packageVersion),
                pkgDownloadContext,
                @"C:\Users\liweihan\.nuget\packages", // nuget globalPackagesFolder
                logger,
                CancellationToken.None), r => true);
        Console.WriteLine(downloadResult.Status.ToString());
    }
    

    最後提供一個解析 nuget globalPackagesFolder 的兩種思路:

    一個是前面有篇文章介紹的,有個默認的配置文件,然後就是默認的配置,寫了一個解析的方法示例,支持 Windows/Linux/Mac:

    {
        var packagesFolder = Environment.GetEnvironmentVariable("NUGET_PACKAGES");
    
        if (string.IsNullOrEmpty(packagesFolder))
        {
            // Nuget globalPackagesFolder resolve
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                var defaultConfigFilePath =
                    $@"{Environment.GetEnvironmentVariable("APPDATA")}\NuGet\NuGet.Config";
                if (File.Exists(defaultConfigFilePath))
                {
                    var doc = new XmlDocument();
                    doc.Load(defaultConfigFilePath);
                    var node = doc.SelectSingleNode("/configuration/config/add[@key='globalPackagesFolder']");
                    if (node != null)
                    {
                        packagesFolder = node.Attributes["value"]?.Value;
                    }
                }
    
                if (string.IsNullOrEmpty(packagesFolder))
                {
                    packagesFolder = $@"{Environment.GetEnvironmentVariable("USERPROFILE")}\.nuget\packages";
                }
            }
            else
            {
                var defaultConfigFilePath =
                    $@"{Environment.GetEnvironmentVariable("HOME")}/.config/NuGet/NuGet.Config";
                if (File.Exists(defaultConfigFilePath))
                {
                    var doc = new XmlDocument();
                    doc.Load(defaultConfigFilePath);
                    var node = doc.SelectSingleNode("/configuration/config/add[@key='globalPackagesFolder']");
                    if (node != null)
                    {
                        packagesFolder = node.Attributes["value"]?.Value;
                    }
                }
    
                if (string.IsNullOrEmpty(packagesFolder))
                {
                    defaultConfigFilePath = $@"{Environment.GetEnvironmentVariable("HOME")}/.nuget/NuGet/NuGet.Config";
                    if (File.Exists(defaultConfigFilePath))
                    {
                        var doc = new XmlDocument();
                        doc.Load(defaultConfigFilePath);
                        var node = doc.SelectSingleNode("/configuration/config/add[@key='globalPackagesFolder']");
                        if (node != null)
                        {
                            packagesFolder = node.Value;
                        }
                    }
                }
    
                if (string.IsNullOrEmpty(packagesFolder))
                {
                    packagesFolder = $@"{Environment.GetEnvironmentVariable("HOME")}/.nuget/packages";
                }
            }
        }
    
        Console.WriteLine($"globalPackagesFolder: {packagesFolder}");
    }
    

    另一個是可以根據 nuget 提供的一個命令查詢 nuget locals global-packages -l,通過命令輸出獲取

    Reference

    • https://github.com/WeihanLi/SamplesInPractice/blob/master/NugetSample/RawApiSample.cs
    • https://github.com/WeihanLi/SamplesInPractice/blob/master/NugetSample/NugetClientSdkSample.cs
    • https://docs.microsoft.com/en-us/nuget/reference/nuget-client-sdk
    • https://docs.microsoft.com/en-us/nuget/create-packages/set-package-type
    • https://docs.microsoft.com/en-us/nuget/api/overview
    • https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • C# 9.0 終於來了, Top-level programs 和 Partial Methods 兩大新特性探究

    C# 9.0 終於來了, Top-level programs 和 Partial Methods 兩大新特性探究

    一:背景

    1. 講故事

    .NET 5 終於在 6月25日 發布了第六個預覽版,隨之而來的是更多的新特性加入到了 C# 9 Preview 中,這個系列也可以繼續往下寫了,廢話不多說,今天來看一下 Top-level programsExtending Partial Methods 兩大新特性。

    2. 安裝必備

    下載最新的 .net 5 preview 6

    下載最新的 Visual Studio 2019 version 16.7 Preview 3.1

    二:新特性研究

    1. Top-level programs

    如果大家玩過 python,應該知道在 xxx.py 中寫一句 print,這程序就能跑起來了,簡單高效又粗暴,很開心的是這特性被帶到了C# 9.0 中。

    • 修改前
    
    using System;
    
    namespace ConsoleApp2
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
            }
        }
    
    
    • 修改后
    
    System.Console.WriteLine("Hello World!");
    
    

    這就有意思了,Main入口函數去哪了? 沒它的話,JIT還怎麼編譯代碼呢? 想知道答案的話用 ILSpy 反編譯看一下就好啦!

    
    .class private auto ansi abstract sealed beforefieldinit $Program
    	extends [System.Runtime]System.Object
    {
    	.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
    		01 00 00 00
    	)
    	// Methods
    	.method private hidebysig static 
    		void $Main (
    			string[] args
    		) cil managed 
    	{
    		// Method begins at RVA 0x2050
    		// Code size 18 (0x12)
    		.maxstack 8
    		.entrypoint
    
    		IL_0000: ldstr "Hello World!"
    		IL_0005: call void [System.Console]System.Console::WriteLine(string)
    		IL_000a: nop
    		IL_000b: call string [System.Console]System.Console::ReadLine()
    		IL_0010: pop
    		IL_0011: ret
    	} // end of method $Program::$Main
    
    } // end of class $Program
    
    
    

    從 IL 上看,類變成了 $Program, 入口方法變成了 $Main, 這就好玩了,在我們的印象中入口函數必須是 Main,否則編譯器會給你一個大大的錯誤,你加了一個 $ 符號,那CLR還能認識嗎? 能不能認識我們用 windbg 看一些託管和非託管堆棧,看看有什麼新發現。

    
    0:010> ~0s
    ntdll!NtReadFile+0x14:
    00007ffe`f8f8aa64 c3              ret
    0:000> !dumpstack
    OS Thread Id: 0x7278 (0)
    Current frame: ntdll!NtReadFile + 0x14
    Child-SP         RetAddr          Caller, Callee
    0000008551F7E810 00007ffed1e841dc (MethodDesc 00007ffe4020d500 + 0x1c System.Console.ReadLine()), calling 00007ffe400ab090
    0000008551F7E840 00007ffe4014244a (MethodDesc 00007ffe401e58f0 + 0x3a $Program.$Main(System.String[])), calling 00007ffe40240f58
    0000008551F7E880 00007ffe9fcc8b43 coreclr!CallDescrWorkerInternal + 0x83 [F:\workspace\_work\1\s\src\coreclr\src\vm\amd64\CallDescrWorkerAMD64.asm:101]
    0000008551F7E8C0 00007ffe9fbd1e03 coreclr!MethodDescCallSite::CallTargetWorker + 0x263 [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:554], calling coreclr!CallDescrWorkerWithHandler [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:56]
    0000008551F7E950 00007ffe9fb8c4e5 coreclr!MethodDesc::IsVoid + 0x21 [F:\workspace\_work\1\s\src\coreclr\src\vm\method.cpp:1098], calling coreclr!MetaSig::IsReturnTypeVoid [F:\workspace\_work\1\s\src\coreclr\src\vm\siginfo.cpp:5189]
    0000008551F7EA00 00007ffe9fb8c4bf coreclr!RunMainInternal + 0x11f [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1488], calling coreclr!MethodDescCallSite::CallTargetWorker [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:266]
    0000008551F7EB30 00007ffe9fb8c30a coreclr!RunMain + 0xd2 [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1559], calling coreclr!RunMainInternal [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1459]
    
    

    從上面堆棧的流程圖看: coreclr!RunMain -> coreclr!MethodDesc -> coreclr!CallDescrWorkerInternal -> $Program.$Main, 確實被調用了,不過有一個重大發現,在 $Program.$Main 調用之前底層的 CLR 讀取了 方法描述符,這就是一個重大突破點,方法描述符在哪裡呢? 可以用 ildasm 去看一下元數據列表。

    可以看到,入口函數那裡打上了一個 ENTRYPOINT 標記,這就說明入口函數名其實是可以隨便更改的,只要被 ENTRYPOINT打上標記即可,CoreCLR就能認的出來~~~

    2. Partial Methods

    我們知道 部分方法 是一個很好的樁函數,而且在 C# 3.0 中就已經實現了,那時候給我們增加了很多限制,如下圖:

    翻譯過來就是:

    • 部分方法的簽名必須一致

    • 方法必須返回void

    • 不允許使用訪問修飾符,而且還是隱式私有的。

    在 C# 9.0 中放開了對 方法簽名 的所有限制,正如 issue 總結:

    這是一個非常好的消息,現在你的部分方法上可以加上各種類型的返回值啦,這裏我舉一個例子:

    
        class Program
        {
            static void Main(string[] args)
            {
                var person = new Person();
    
                Console.WriteLine(person.Run("jack"));
            }
        }
    
        public partial class Person
        {
            public partial string Run(string name);
        }
    
        public partial class Person
        {
            public partial string Run(string name) => $"{name}:開溜了~";
        }
    
    

    然後我們用 ILSpy 簡單看看底層怎麼玩的,如下圖可以看到其實就是一個簡單的合成,對吧。

    現在我有想法了,如果我不給 Run 方法實現會怎麼樣? 把下面的 partial 類註釋掉看一下。

    從報錯信息看,可訪問的修飾符必須要有方法實現,還以為直接編譯的時候抹掉呢。 這就起不到樁函數的作用:-D,不過這個特性還是給了我們更多的可能用的到的應用場景吧。

    三:總結

    本篇兩個特性還是非常實用的,Top-level programs 讓我們可以寫更少的代碼,甚至拿起 記事本 都可以快捷的編寫類似一次性使用的測試代碼, Partial Methods 特性留給大家補充吧,我基本上算是沒用過 (┬_┬)。

    如您有更多問題與我互動,掃描下方進來吧~

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※回頭車貨運收費標準

  • 台灣團隊以《海洋危機》出席全球最大桌遊展

    摘錄自2019年11月4日自由時報報導

    全球最大桌上遊戲大會「德國埃森桌遊展(SPIEL)」上月下旬開展時,台灣業者獨闖,靠實力獲邀參與官方論壇主講「環境友善」議題,直接正名Taiwan登上官網與活動介紹,不是以China(中國)或Chinese Taipei(中華台北)名稱參與,更透過桌遊,將台灣文化輸出全世界。

    獨立遊戲出版業者「綿羊犬百寶箱」公司負責人林啟維表示,SPIEL桌遊展是全球最大,展期是上月24至27日,今年便8月收到該展邀請,希望出席大會在上月26日舉辦的官方論壇活動,主講「環境友善」議題,便將今年開發的《海洋危機》獲台灣逾600間學校使用的經驗,到場分享。

    林啟維說,論壇中看見德國遊戲市場與亞洲新興市場的差異,永續話題也在當場彼此交鋒,但結束後卻有不少德國、荷蘭等地學校老師、環境工作者現身,指定購買台灣桌遊,另外過去也開發台灣內容的《史前歷險紀》,不少外國人玩完才發現是台灣史前文化,同樣把台灣文化輸出海外。

    林啟維認為,「用熱情、專業將自己手邊的事情做好,當機會來臨,我們就會被看見。」而桌遊設計領域,一直由自由派的創作者們領導著,而台灣在遊戲設計與市場成熟度,也大大領先中國,因此這次論壇無任何政治干預,讓自已不僅代表台灣,也更代表東亞桌遊開發與應用的精神,未來將繼續努力,持續在國際舞台綻放。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • HTML&CSS面試高頻考點(二)

    HTML&CSS面試高頻考點(二)

    HTML&CSS面試高頻考點(一)    

    6. W3C盒模型與怪異盒模型

    • 標準盒模型(W3C標準)
    • 怪異盒模型(IE標準)

    怪異盒模型下盒子的大小=width(content + border + padding) + margin,即真實大小

    *參考標準模式與兼容模式的區別,兼容模式下為怪異盒模型。

    *注意box-sizing可以改變盒模型(box-sizing:border-box即為怪異盒模型)。

    7. 水平垂直居中的方法

    (1)定寬居中

    1. absolute + 負margin

    //父元素
    position: relative;
    //子元素
    position: absolute;
    top: 50%;
    left: 50%;
    //margin設置自身一半的距離
    margin-top: -50px;
    margin-left: -50px;

    2. absolute + margin: auto

    //父元素
    position: relative;
    //子元素
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;

     3. absolute + calc

    //父元素
    position: relative;
    //子元素
    position: absolute;
    //減去自身一半的寬高
    top: calc(50% - 50px);
    left: calc(50% - 50px);

     *calc() 函數用於動態計算長度值。

     4. min-height: 100vh + flex + margin:auto

    main{   min-height: 100vh;
       /* vh相對於視窗的高度,視窗高度是100vh */
      /* “視區”所指為瀏覽器內部的可視區域大小,   不包含任務欄標題欄以及底部工具欄的瀏覽器區域大小。 */   display: flex;
    } div{   margin: auto;
    }

    (2)不定寬居中

    1. absolute + transform

    //父元素
    position: relative;
    //子元素
    position: absolute;
    top:50%;
    left:50%;
    transform:translate(-50%,-50%);

    2. line-height

    //父元素 .wp { text-align: center; line-height: 300px;
    }
    //子元素
    .box { display: inline-block; vertical-align: middle; line-height: inherit; text-align: left; }

    3. flex布局

    display: flex;//flex布局
    justify-content: center;//使子項目水平居中
    align-items: center;//使子項目垂直居中

    4. table-cell布局

    因為table-cell相當與表格的td,無法設置寬和高,所以嵌套一層,嵌套一層必須設置display: inline-block

    <div class="box">
        <div class="content">
            <div class="inner">
            </div>
        </div>
    </div> .box { //只有這裏可以設置寬高 display: table; //這是嵌套的一層,會被table-cell覆蓋 } .content { display: table-cell; vertical-align: middle;//使子元素垂直居中 text-align: center;//使子元素水平居中 } .inner { display: inline-block; //子元素 }

    8. BFC

     前文鏈接:點擊這裏

    BFC:Block formatting context(塊級格式化上下文),是一個獨立的渲染區域,只有Block-level box參与,與外部區域毫不相干。

    • block-level box:display屬性為block, list-item, table的元素。
    • inline-level box:display屬性為inline, inline-box, inline-table的元素。

    (1)BFC的布局規則

    • 內部box在垂直方向一個個放置;
    • 同一個BFC的兩個相鄰box的margin會發生重疊;
    • 每個盒子的margin左邊與包含塊的border左邊相接觸,即使存在浮動也是如此;
    • BFC區域不會和float box重疊;
    • 計算BFC高度時,浮動元素也參与計算。

    (2)開啟BFC的方法

    • float的值不是none
    • position的值不是static或relative
    • display的值是inline-block, table-cell, flex, table-caption或inline-flex
    • overflow的值不是visible

    (3)BFC的作用

    1. 避免margin塌陷

    根據BFC的布局規則2,我們可以通過設置兩個不同的BFC的方式解決margin塌陷的問題。

    2. 自適應兩欄布局

    根據BFC的布局規則3和4,我們將右側div開啟BFC就可以形成自適應兩欄布局。

    .left { float: left; //左側浮動 }

    .left { float: left;
    } .right { overflow: hidden; //開啟BFC }

    3. 清除浮動

    當不給父節點設置高度的時候,如果子節點設置浮動,父節點會發生高度塌陷。這個時候就要清除浮動。

    根據規則5,只需給父元素激活BFC就可以達到目的。

    .par { overflow: hidden; //父元素開啟BFC } .child { float: left; //子元素浮動 }

    9. 清除浮動

     這篇有寫:點這裏

    10. position屬性

     這篇有寫:點這裏

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?