国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

.NET Emit 入門教程:第二部分:構(gòu)建動(dòng)態(tài)程序集(追加構(gòu)建靜態(tài)程序集教程)

這篇具有很好參考價(jià)值的文章主要介紹了.NET Emit 入門教程:第二部分:構(gòu)建動(dòng)態(tài)程序集(追加構(gòu)建靜態(tài)程序集教程)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

前言:

在本部分中,我們將深入探討如何使用C# Emit 來(lái)創(chuàng)建動(dòng)態(tài)程序集。

動(dòng)態(tài)程序集是在運(yùn)行時(shí)生成的,為我們提供了一種靈活、動(dòng)態(tài)地構(gòu)建和加載程序集的能力。

1. 程序集的概念

程序集是.NET中的基本部署單位,它包含了可執(zhí)行代碼、資源、元數(shù)據(jù)等信息,是.NET應(yīng)用程序的基本組成單元之一。

與靜態(tài)程序集(即程序集持久化)不同,動(dòng)態(tài)程序集是在運(yùn)行時(shí)生成的,使得我們可以根據(jù)需要?jiǎng)討B(tài)地構(gòu)建和加載程序集。

動(dòng)態(tài)程序集的重要性體現(xiàn)在多個(gè)方面,包括但不限于模塊化、版本控制、代碼復(fù)用等。

通過(guò)動(dòng)態(tài)程序集,我們可以更好地管理和組織代碼,實(shí)現(xiàn)更靈活的程序設(shè)計(jì)和開(kāi)發(fā)。

2、Emit?構(gòu)建程序集支持情況:

.Net 系列:動(dòng)態(tài)程序集:支持;程序集持久化:支持。

.Net Core 系列:動(dòng)態(tài)程序集:支持;程序集持久化不支持。
?

3、Emit 創(chuàng)建動(dòng)態(tài)程序集:

在C#中,操作程序集的核心類是:AssemblyBuilder。

在這過(guò)程,我們可以使用??AssemblyName?來(lái)定義程序集的名稱和版本等信息。

AssemblyName assemblyName = new AssemblyName("MyDllName") { Version = new Version("1.0.0.0") };

創(chuàng)建程序集對(duì)象,在 .Net?和 .Net Core 中有所不同:

.NET?代碼:通過(guò)?AppDomain.DefineDynamicAssembly 來(lái)創(chuàng)建動(dòng)態(tài)程序集對(duì)象:

AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

AssemblyBuilderAccess 在 .Net?系列中的屬性:

AssemblyBuilderAccess.Run; 表示程序集可被執(zhí)行,但不能被保存?! ?AssemblyBuilderAccess.Save; 表示程序集可被保存,但不能被執(zhí)行?! ?AssemblyBuilderAccess.RunAndSave; 表示程序集可被保存并能被執(zhí)行。
AssemblyBuilderAccess.ReflectionOnly; 表示程序集只能用于反射上下文環(huán)境中,不能被執(zhí)行?!?AssemblyBuilderAccess.RunAndCollect; 表示程序集可以被卸載并且內(nèi)存會(huì)被回收

.NET Core?代碼:通過(guò) AssemblyBuilder.DefineDynamicAssembly?來(lái)創(chuàng)建動(dòng)態(tài)程序集對(duì)象:

AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

AssemblyBuilderAccess 在 .Net Core?系列中的屬性:

AssemblyBuilderAccess.Run; 表示程序集可被執(zhí)行,但不能被保存?! ?AssemblyBuilderAccess.Collect; 表示程序集可以被卸載并且內(nèi)存會(huì)被回收
?

可以看到,目前版本是不支持持久化功能。

4:總結(jié)一:

在本章節(jié)中,我們討論了如何使用 C# Emit 來(lái)構(gòu)建動(dòng)態(tài)程序集,以獲得?AssemblyBuilder?這個(gè)程序集構(gòu)建器,開(kāi)啟構(gòu)建程序集的第一步。

在之后的文章,我們會(huì)講解如何用它的 DefineDynamicModule 來(lái)定義模塊,以之后構(gòu)建類、成員、方法等,來(lái)實(shí)現(xiàn)構(gòu)建完整的程序集。

當(dāng)然,對(duì)于構(gòu)建動(dòng)態(tài)程序集,本文章到此會(huì)顯的有點(diǎn)簡(jiǎn)單,為了避免被大伙說(shuō)文章太水。

于是,打算追加一下對(duì)于構(gòu)建靜態(tài)程序集(即持久化程序集)的相關(guān)知識(shí)。

構(gòu)建靜態(tài)程序集的三種方式:

.Net 系列:使用 EmitCodeDom(System.CodeDom.Compiler 系統(tǒng)集成)

.Net Core 系列:Roslyn(Microsoft.CodeAnalysis.CSharp 需要引用組件包)

5、Emit?構(gòu)建靜態(tài)程序集:

在上述代碼中,我們通過(guò) AssemblyName?來(lái)指定程序集名稱和版本號(hào)。

如果我們希望持久化程序集,并將程序集分發(fā)給其它人調(diào)用,則需要補(bǔ)充更多的相關(guān)信息:

比如:Taurus.MVC 微服務(wù)組件中就實(shí)現(xiàn)了動(dòng)態(tài)生成 Rpc 調(diào)用程序集,以供其它微服務(wù)節(jié)點(diǎn)調(diào)用。

在定義完程序集名稱和版本后(AssemblyBuilderAccess?需要指定為?RunAndSave )。

我們可以通過(guò) AssemblyBuilder? 的 SetCustomAttribute?方法,來(lái)添加自定義屬性,最后通過(guò) Save?方法,來(lái)持久化程序集:

internal class Program
{
    static void Main(string[] args)
    {
        string dllName = "MyDynamic";
        string title = "This is a dynamic title.";

        AssemblyName assemblyName = new AssemblyName(dllName) { Version = new Version("3.0.0.0") };
        AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);

        // 添加自定義屬性到程序集var titleAttr = new CustomAttributeBuilder(
           typeof(AssemblyTitleAttribute).GetConstructor(new Type[] { typeof(string) }),
           new object[] { title }
       );
        assemblyBuilder.SetCustomAttribute(titleAttr);

        assemblyBuilder.DefineVersionInfoResource();
       
        assemblyBuilder.Save(dllName + ".dll");

        Console.WriteLine("程序集已生成");
    }
}

自定義支持哪些屬性,可以參考工程目錄下的:AssemblyInfo.cs?信息:

.NET Emit 入門教程:第二部分:構(gòu)建動(dòng)態(tài)程序集(追加構(gòu)建靜態(tài)程序集教程)

沒(méi)有指定完整的保存路徑時(shí),程序運(yùn)行之后默認(rèn)在運(yùn)行目錄下可以看到生成的程序集:

.NET Emit 入門教程:第二部分:構(gòu)建動(dòng)態(tài)程序集(追加構(gòu)建靜態(tài)程序集教程)

通過(guò)反編繹工具,可以看到程序集的相關(guān)信息:

.NET Emit 入門教程:第二部分:構(gòu)建動(dòng)態(tài)程序集(追加構(gòu)建靜態(tài)程序集教程)

在上面的示例代碼中,我們追加了一行代碼如下:

assemblyBuilder.DefineVersionInfoResource();

它讓生成的程序集在 Window 平臺(tái)可以看到相關(guān)信息,(不寫入的話,相關(guān)內(nèi)容為空):

.NET Emit 入門教程:第二部分:構(gòu)建動(dòng)態(tài)程序集(追加構(gòu)建靜態(tài)程序集教程)

6、使用 CodeDom 生成靜態(tài)程序集

CodeDom 的使用比較簡(jiǎn)單,無(wú)需要引用組件,代碼編寫也比較簡(jiǎn)潔,唯一的缺點(diǎn),就是不支持 .NET Core?系列。

使用示例代碼來(lái)自Taurus.MVC?微服務(wù)RPC代碼生成(CodeDom?版本):

更多源碼:https://github.com/cyq1162/Taurus.MVC/tree/master/src/Taurus.Core/Plugin/MicroService/Client/Proxy/DotNet

 /// <summary>
 /// Rpc 客戶端代理生成類
 /// </summary>
 internal static class RestProxyCreator
 {
     /// <summary>
     /// 構(gòu)建并保存程序集
     /// </summary>
     /// <param name="assName">程序集名稱</param>
     /// <param name="savePath">保存路徑</param>
     public static bool BuildAssembly(string assName, string savePath)
     {
         if (string.IsNullOrEmpty(assName)) { assName = "RpcProxy"; }
         if (string.IsNullOrEmpty(savePath))
         {
             savePath = AppConst.WebRootPath + assName + ".dll";
         }
         else if (!savePath.StartsWith(AppConst.WebRootPath))
         {
             savePath = AppConst.WebRootPath + savePath;
         }
         string version;
         var code = RestProxyCoder.CreateCode(assName, out version);
         var title = assName + " for Taurus MicroService, build on .net " + Environment.Version.ToString();
         var versionCode = RestProxyCoder.CreateVersionCode(title, title, version);

         CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
         CompilerParameters cp = new CompilerParameters();
         cp.ReferencedAssemblies.Add("System.dll");
         cp.ReferencedAssemblies.Add("System.Web.dll");
         cp.ReferencedAssemblies.Add("System.Xml.dll");
         cp.ReferencedAssemblies.Add("System.Data.dll");
         cp.ReferencedAssemblies.Add(AppConst.AssemblyPath + "CYQ.Data.dll");
         cp.ReferencedAssemblies.Add(AppConst.AssemblyPath + "Taurus.Core.dll");
         cp.GenerateExecutable = false;
         cp.GenerateInMemory = false;
         cp.OutputAssembly = savePath;
         CompilerResults cr = provider.CompileAssemblyFromSource(cp, versionCode, code);
         if (cr == null || cr.Errors.Count > 0) { return false; }
         return true;

     }
 }

7、?使用 Roslyn?生成靜態(tài)程序集

Roslyn?需要引用組件,根據(jù)自己要支持的最低版本進(jìn)行引用(如 4.1.0 就是最低支持.NET Core 2.1的版本):

.NET Emit 入門教程:第二部分:構(gòu)建動(dòng)態(tài)程序集(追加構(gòu)建靜態(tài)程序集教程)

而且使用麻煩,兩個(gè)距坑:

1、Win32 資源信息如何顯示。

2、程序集引用路徑錯(cuò)誤問(wèn)題。

為解決這兩個(gè)距坑問(wèn)題,費(fèi)了不少時(shí)間和精力,畢竟網(wǎng)上國(guó)內(nèi)外只有零散的引導(dǎo)信息,還有那不靠譜的 GPT 系列。

使用示例代碼來(lái)自 Taurus.MVC?微服務(wù)RPC代碼生成(Roslyn 版本):

更多源碼:https://github.com/cyq1162/Taurus.MVC/tree/master/src/Taurus.Core/Plugin/MicroService/Client/Proxy/NetCore

/// <summary>
/// Rpc 客戶端代理生成類
/// </summary>
internal static class RestProxyCreator
{
    /// <summary>
    /// 構(gòu)建并保存程序集
    /// </summary>
    /// <param name="assName">程序集名稱</param>
    /// <param name="savePath">保存路徑</param>
    public static bool BuildAssembly(string assName, string savePath)
    {
        if (string.IsNullOrEmpty(assName)) { assName = "RpcProxy"; }
        if (string.IsNullOrEmpty(savePath))
        {
            savePath = AppConst.WebRootPath + assName + ".dll";
        }
        else if (!savePath.StartsWith(AppConst.WebRootPath))
        {
            savePath = AppConst.WebRootPath + savePath;
        }
        string version;
        var code = RestProxyCoder.CreateCode(assName, out version);
        var title = assName + " for Taurus MicroService, build on .netcore " + Environment.Version.ToString();
        var versionCode = RestProxyCoder.CreateVersionCode(title, title, version);

        SyntaxTree syntaxVersionTree = CSharpSyntaxTree.ParseText(versionCode);
        SyntaxTree syntaxCodeTree = CSharpSyntaxTree.ParseText(code);


        // 定義編譯選項(xiàng)
        CSharpCompilationOptions compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
        .WithOptimizationLevel(OptimizationLevel.Release); // 設(shè)置優(yōu)化級(jí)別

        // 創(chuàng)建 Compilation
        CSharpCompilation compilation = CSharpCompilation.Create(assName,
            new[] { syntaxVersionTree, syntaxCodeTree },
            references: AddRef(),
            options: compilationOptions);

        // 編譯并生成程序集
        using (MemoryStream ms = new MemoryStream())
        {
            using (Stream win32resStream = compilation.CreateDefaultWin32Resources(
                                                                        versionResource: true, // 生成版本號(hào)。
                                                                        noManifest: false,
                                                                        manifestContents: null,
                                                                        iconInIcoFormat: null))
            {

                EmitResult result = compilation.Emit(ms, win32Resources: win32resStream);

                if (!result.Success)
                {
                    //foreach (var diagnostic in result.Diagnostics)
                    //{
                    //    Console.WriteLine(diagnostic);
                    //}
                    //Console.WriteLine("fail....");
                    return false;
                }
                else
                {
                    // 保存程序集到文件
                    using (FileStream file = new FileStream(savePath, FileMode.Create))
                    {
                        ms.Seek(0, SeekOrigin.Begin);
                        ms.CopyTo(file);
                    }
                    //Console.WriteLine("OK....");
                }
            }
        }

        return true;

    }

    /// <summary>
    /// 添加程序集引用
    /// </summary>
    /// <returns></returns>
    private static PortableExecutableReference[] AddRef()
    {
        List<PortableExecutableReference> exeRefs = new List<PortableExecutableReference>();

        string path = typeof(object).Assembly.Location;

        #region 引用路徑修正
        path = Path.GetDirectoryName(path);
        if (path.Contains("\\shared\\Microsoft.NETCore.App"))
        {
            // windows 平臺(tái),這是nuget 實(shí)現(xiàn)程序集路徑
            string refPath = path.Replace("\\shared\\Microsoft.NETCore.App", "\\\\packs\\Microsoft.NETCore.App.Ref") + "\\ref";
            if (Directory.Exists(refPath))
            {
                string[] files = Directory.GetDirectories(refPath);
                if (files.Length > 0) { path = files[0] + "\\"; }
            }
        }
        #endregion
        foreach (string dllFilePath in Directory.GetFiles(path, "*.dll"))
        {
            var dll = Path.GetFileName(dllFilePath);

            if (dll.Split(".").Length > 4) { continue; }
            if (dll.StartsWith("Microsoft.")) { continue; }
            if (dll.StartsWith("System.Drawing.")) { continue; }
            if (dll.StartsWith("System.IO.")) { continue; }
            if (dll.StartsWith("System.Linq.")) { continue; }
            if (dll.StartsWith("System.Net.")) { continue; }
            if (dll.StartsWith("System.Reflection.")) { continue; }
            if (dll.StartsWith("System.Security.")) { continue; }
            if (dll.StartsWith("System.Text.")) { continue; }
            if (dll.StartsWith("System.Threading.")) { continue; }
            if (dll.StartsWith("System.Globalization.")) { continue; }
            if (dll.StartsWith("System.Resources.")) { continue; }
            if (dll.StartsWith("System.Transactions.")) { continue; }
            if (dll.StartsWith("System.Memory.")) { continue; }
            if (dll.StartsWith("System.Formats.")) { continue; }
            if (dll.StartsWith("System.ComponentModel.")) { continue; }
            if (dll.StartsWith("System.Windows.")) { continue; }
            if (dll.StartsWith("System.Diagnostics.")) { continue; }
            if (dll.Contains("VisualBasic")) { continue; }


            exeRefs.Add(MetadataReference.CreateFromFile(dllFilePath));
        }


        //添加引用程序集
        string cyqdata = AppConst.AssemblyPath + "CYQ.Data.dll";
        string taurus = AppConst.AssemblyPath + "Taurus.Core.dll";

        exeRefs.Add(MetadataReference.CreateFromFile(cyqdata));
        exeRefs.Add(MetadataReference.CreateFromFile(taurus));
        return exeRefs.ToArray();
    }
}

8、總結(jié):

在本章節(jié)中,我們討論了如何使用 C# Emit 來(lái)構(gòu)建動(dòng)態(tài)程序集,以獲得?AssemblyBuilder?這個(gè)程序集構(gòu)建器,開(kāi)啟構(gòu)建程序集的第一步。

同時(shí)我們也討論了如何使用 C# Emit 來(lái)構(gòu)建動(dòng)態(tài)程序集以及程序集的持久化。

同時(shí)還分享了自己的干貨,如何使用 CodeDom?和 Roslyn?來(lái)構(gòu)建靜態(tài)程序集。

通過(guò)本章節(jié)的內(nèi)容,讀者可以掌握如何利用 C# Emit 技術(shù)構(gòu)建動(dòng)態(tài)程序集和靜態(tài)程序集,從而實(shí)現(xiàn)靈活、動(dòng)態(tài)的程序設(shè)計(jì)和開(kāi)發(fā)。

動(dòng)態(tài)程序集的應(yīng)用能夠提升代碼的模塊化性、版本控制和代碼復(fù)用性,為.NET應(yīng)用程序的開(kāi)發(fā)提供更多可能性。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-842096.html

到了這里,關(guān)于.NET Emit 入門教程:第二部分:構(gòu)建動(dòng)態(tài)程序集(追加構(gòu)建靜態(tài)程序集教程)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • .NET Emit 入門教程:第六部分:IL 指令:3:詳解 ILGenerator 指令方法:參數(shù)加載指令

    .NET Emit 入門教程:第六部分:IL 指令:3:詳解 ILGenerator 指令方法:參數(shù)加載指令

    在上一篇中,我們介紹了 ILGenerator 輔助方法。 本篇,將詳細(xì)介紹指令方法,并詳細(xì)介紹指令的相關(guān)用法。 在接下來(lái)的教程,關(guān)于IL指令部分,會(huì)將指令分為以下幾個(gè)分類進(jìn)行講解: 下面開(kāi)始介紹第一部分,參數(shù)加載指令: 參數(shù)加載指令用于在方法中加載參數(shù)到操作數(shù)棧中,

    2024年04月08日
    瀏覽(19)
  • .NET Emit 入門教程:第六部分:IL 指令:6:詳解 ILGenerator 指令方法:方法調(diào)用指令

    .NET Emit 入門教程:第六部分:IL 指令:6:詳解 ILGenerator 指令方法:方法調(diào)用指令

    經(jīng)過(guò)前面幾篇的學(xué)習(xí),我們了解到指令的大概分類,如: 參數(shù)加載指令,該加載指令以?Ld 開(kāi)頭,將參數(shù)加載到棧中,以便于后續(xù)執(zhí)行操作命令。 參數(shù)存儲(chǔ)指令,其指令以 St 開(kāi)頭,將棧中的數(shù)據(jù),存儲(chǔ)到指定的變量中,以方便后續(xù)使用。 創(chuàng)建實(shí)例指令,其指令以 New 開(kāi)頭,

    2024年04月08日
    瀏覽(20)
  • .NET Emit 入門教程:第六部分:IL 指令:4:詳解 ILGenerator 指令方法:參數(shù)存儲(chǔ)指令

    .NET Emit 入門教程:第六部分:IL 指令:4:詳解 ILGenerator 指令方法:參數(shù)存儲(chǔ)指令

    上一篇介紹了?IL?指令的分類以及參數(shù)加載指令,該加載指令以ld開(kāi)頭,將參數(shù)加載到棧中,以便于后續(xù)執(zhí)行操作命令。 本篇開(kāi)始介紹參數(shù)存儲(chǔ)指令,其指令以st開(kāi)頭,將棧中的數(shù)據(jù),存儲(chǔ)到指定的變量中,以方便后續(xù)使用。 在 IL 中,除了參數(shù)存儲(chǔ)指令 starg 和 stloc 之外,還

    2024年04月08日
    瀏覽(19)
  • .NET Emit 入門教程:第六部分:IL 指令:9:詳解 ILGenerator 指令方法:運(yùn)算操作指令(指令篇結(jié)束)

    .NET Emit 入門教程:第六部分:IL 指令:9:詳解 ILGenerator 指令方法:運(yùn)算操作指令(指令篇結(jié)束)

    經(jīng)過(guò)前面幾篇的學(xué)習(xí),我們了解到指令的大概分類,如: 參數(shù)加載指令,該加載指令以?Ld 開(kāi)頭,將參數(shù)加載到棧中,以便于后續(xù)執(zhí)行操作命令。 參數(shù)存儲(chǔ)指令,其指令以 St 開(kāi)頭,將棧中的數(shù)據(jù),存儲(chǔ)到指定的變量中,以方便后續(xù)使用。 創(chuàng)建實(shí)例指令,其指令以 New 開(kāi)頭,

    2024年04月22日
    瀏覽(21)
  • Python機(jī)器學(xué)習(xí)算法入門教程(第二部分)

    Python機(jī)器學(xué)習(xí)算法入門教程(第二部分)

    接著Python機(jī)器學(xué)習(xí)算法入門教程(第一部分),繼續(xù)展開(kāi)描述。 在 Python機(jī)器學(xué)習(xí)算法入門教程(第一部分)中的第六部分:線性回歸:損失函數(shù)和假設(shè)函數(shù) 一節(jié),從數(shù)學(xué)的角度解釋了假設(shè)函數(shù)和損失函數(shù),我們最終的目的要得到一個(gè)最佳的“擬合”直線,因此就需要將損失

    2024年02月05日
    瀏覽(21)
  • 【監(jiān)控儀表系統(tǒng)】Grafana 中文入門教程 | 構(gòu)建你的第一個(gè)儀表盤

    【監(jiān)控儀表系統(tǒng)】Grafana 中文入門教程 | 構(gòu)建你的第一個(gè)儀表盤

    Grafana 讀音:/gr??fɑ?n?ɑ?/ 在大廠工作久了,時(shí)常對(duì)一些工具的存在覺(jué)得理所當(dāng)然。 比如說(shuō),需要計(jì)算資源的時(shí)候,一個(gè)配置文件就可以要來(lái)兩百臺(tái)虛擬化好的機(jī)子。需要試下緩存?點(diǎn)下鼠標(biāo)就可以要到幾十個(gè)配置好的 Redis 結(jié)點(diǎn)。 最省心的是,這些工具都已經(jīng)根據(jù)工作流

    2024年02月02日
    瀏覽(24)
  • 【Maven教程】(一)入門介紹篇:Maven基礎(chǔ)概念與其他構(gòu)建工具:理解構(gòu)建過(guò)程與Maven的多重作用,以及與敏捷開(kāi)發(fā)的關(guān)系 ~

    【Maven教程】(一)入門介紹篇:Maven基礎(chǔ)概念與其他構(gòu)建工具:理解構(gòu)建過(guò)程與Maven的多重作用,以及與敏捷開(kāi)發(fā)的關(guān)系 ~

    \\\" Maven \\\"可以翻譯為 “知識(shí)的積累者” 或 “專家”。這個(gè)詞源于波斯語(yǔ),意為廣受尊重和富有智慧的人。在軟件開(kāi)發(fā)領(lǐng)域中,Maven作為Apache 組織中的一個(gè)頗為成功的開(kāi)源項(xiàng)目,它是一個(gè)非常流行的構(gòu)建工具,它在項(xiàng)目管理、依賴管理和構(gòu)建自動(dòng)化方面提供了強(qiáng)大的功能和支持

    2024年02月12日
    瀏覽(87)
  • 小程序入門——詳細(xì)教程

    小程序入門——詳細(xì)教程

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? 艷艷耶??:個(gè)人主頁(yè) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 個(gè)人專欄 :《Spring與Mybatis集成整合》《Vue.js使用》 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? 生活的理想,

    2024年02月06日
    瀏覽(16)
  • 小程序入門級(jí)教程

    小程序入門級(jí)教程

    小程序,這里主要說(shuō)的是微信小程序,微信小程序是在16年推出的,同樣的,微信小程序的競(jìng)品也有很多,比如:支付寶小程序,釘釘,美團(tuán),頭條,抖音,qq小程序等等 可以實(shí)現(xiàn)自由分享 不用下載app也可使用 能快速的開(kāi)發(fā),使用微信接口 小程序是面向大眾的,針對(duì)開(kāi)發(fā)者

    2024年02月10日
    瀏覽(46)
  • 微信小程序入門教程 --(保姆級(jí))

    微信小程序入門教程 --(保姆級(jí))

    一、小程序注冊(cè) 1、首先,到小程序官網(wǎng)注冊(cè)自己的小程序賬號(hào),以下附有地址和教程: 小程序官網(wǎng) 進(jìn)入這個(gè)地址之后,會(huì)看到這樣的頁(yè)面,點(diǎn)擊立即注冊(cè)按鈕 2、在接下來(lái)的頁(yè)面,選擇小程序 3、然后根據(jù)提示完成三個(gè)注冊(cè)步驟,(1).填寫正確的郵箱和密碼格式;(2).進(jìn)行郵箱

    2023年04月08日
    瀏覽(17)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包