必备 .NET - C# 脚本
作者:Mark Michaelis | 2016 年 1 月
Link: https://msdn.microsoft.com/zh-cn/magazine/mt614271.aspx
随着 Visual Studio 2015 Update 1(下文简称 Update 1)的发布,引出了全新的 C# 读取-求值-打印-循环 (REPL),它可作为 Visual Studio 2015 内的全新交互窗口或新命令行接口 (CLI),称为 CSI。除了将 C# 语言引入命令行外,Update 1 还引入了全新的 C# 脚本语言,以前通常保存到 CSX 文件。
深入探讨全新 C# 脚本之前,必须了解目标场景。C# 脚本是一款用于测试 C# 和 .NET 代码段的工具,无需创建多个单元测试或控制台项目。它提供了轻型选项,可快速在命令行上对 LINQ 聚合方法进行编码、检查 .NET API 是否解压缩文件或调用 REST API,以了解返回的内容或工作原理。它提供了探索和了解 API 的简便方法,无需对 %TEMP% 目录中的另一个 CSPROJ 文件支付开销。
C# REPL 命令行界面 (CSI.EXE)
正如学习 C# 自身,入手学习 C# REPL 界面的最好方法是运行它并开始执行命令。要启动它,从 Visual Studio 2015 开发者命令提示符运行命令 csi.exe,或使用完整路径 C:\Program Files (x86)\MSBuild\14.0\bin\csi.exe。从此处开始执行 C# 语句,如图 1 所示。
图 1 CSI REPL 示例
C:\Program Files (x86)\Microsoft Visual Studio 14.0>csi
Microsoft (R) Visual C# Interactive Compiler version 1.1.0.51014
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help"
for more information.
> System.Console.WriteLine("Hello! My name is Inigo Montoya");
Hello! My name is Inigo Montoya
>
> ConsoleColor originalConsoleColor = Console.ForegroundColor;
> try{
. Console.ForegroundColor = ConsoleColor.Red;
. Console.WriteLine("You killed my father. Prepare to die.");
. }
. finally
. {
. Console.ForegroundColor = originalConsoleColor;
. }
You killed my father. Prepare to die.
> IEnumerable<Process> processes = Process.GetProcesses();
> using System.Collections.Generic;
> processes.Where(process => process.ProcessName.StartsWith("c") ).
. Select(process => process.ProcessName ).Distinct()
DistinctIterator { "chrome", "csi", "cmd", "conhost", "csrss" }
> processes.First(process => process.ProcessName == "csi" ).MainModule.FileName
"C:\\Program Files (x86)\\MSBuild\\14.0\\bin\\csi.exe"
> $"The current directory is { Environment.CurrentDirectory }."
"The current directory is C:\\Program Files (x86)\\Microsoft Visual Studio 14.0."
>
首先注意到的显然是—它类似于 C#—尽管是 C# 新的方言(但整个生产程序没有任何繁琐程序,且在应急原型中是不必要的)。因此,正如您所期望的那样,如果您想要调用静态方法,您可以写出完全限定的方法名称并在圆括号内传递参数。正如在 C# 中,您通过将变量添加为类型的前缀来声明变量,并在声明时选择性地分配给它一个新值。同样,正如您所期望的那样,任何有效方法正文语法—try/catch/finally 块、变量声明、Lambda 表达式和 LINQ—均可无缝运行。
即使在命令行上,其他 C# 功能也可保持,如字符串构造(区分大小写、字符串文本和字符串插值)。因此,当您要使用或输出路径时,需要使用 C# 转义字符 ("\") 或字符串文本避开反斜杠,如同 csi.exe 路径输出中的双反斜杠。字符串插值运行方式也如同图 1 演示的"当前目录"示例行,
尽管 C# 脚本支持的远不止语句和表达式。您可以声明自定义类型、通过属性嵌入类型元数据,甚至可以使用特定于 C# 脚本的陈述句简化赘言。考虑图 2 中的拼写检查示例。
图 2 C# 脚本类拼写 (Spell.csx)
#r ".\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll"
#load "Mashape.csx" // Sets a value for the string Mashape.Key
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public
class Spell
{
[JsonProperty("original")]
public
string Original { get; set; }
[JsonProperty("suggestion")]
public
string Suggestion { get; set; }
[JsonProperty(PropertyName ="corrections")]
private JObject InternalCorrections { get; set; }
public IEnumerable<string> Corrections
{
get
{
if (!IsCorrect)
{
return InternalCorrections?[Original].Select(
x => x.ToString()) ?? Enumerable.Empty<string>();
}
else
return Enumerable.Empty<string>();
}
}
public
bool IsCorrect
{
get { return Original == Suggestion; }
}
static
public
bool Check(string word, out IEnumerable<string> corrections)
{
Task <Spell> taskCorrections = CheckAsync(word);
corrections = taskCorrections.Result.Corrections;
return taskCorrections.Result.IsCorrect;
}
static
public
async Task<Spell> CheckAsync(string word)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
$"https://montanaflynn-spellcheck.p.mashape.com/check/?text={ word }");
request.Method = "POST";
request.ContentType = "application/json";
request.Headers = new WebHeaderCollection();
// Mashape.Key is the string key available for
// Mashape for the montaflynn API.
request.Headers.Add("X-Mashape-Key", Mashape.Key);
using (HttpWebResponse response =
await request.GetResponseAsync() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
throw
new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
using(Stream stream = response.GetResponseStream())
using(StreamReader streamReader = new StreamReader(stream))
{
string strsb = await streamReader.ReadToEndAsync();
Spell spell = Newtonsoft.Json.JsonConvert.DeserializeObject<Spell>(strsb);
// Assume spelling was only requested on first word.
return spell;
}
}
}
}
大多数情况下,这只是标准的 C# 类声明。但是,存在多个特定 C# 脚本功能。首先,#r 指令用于引用外部程序集。在本例中,引用的是 Newtonsoft.Json.dll,可帮助分析 JSON 数据。但是请注意,这是一个旨在引用文件系统中文件的指令。同样,它不需要反斜杠转义序列的不必要的繁琐程序。
其次,您可以获得整个列表并将其另存为 CSX 文件,然后使用 #load Spell.csx 将文件"导入"或"内联"到 C# REPL 窗口。#load 指令允许您包括其他脚本文件,犹如所有 #load 文件包括在相同的"项目"或"编译"中。
将代码放入单独的 C# 脚本文件可启用文件重构的类型,更重要的是,能够永久保存 C# 脚本。
使用声明是 C# 脚本中支持的另一个 C# 语言功能,图 2 利用了多次。请注意,与 C# 一样,使用的声明仅限于文件。因此,如果您从 REPL 窗口调用 #load Spell.csx,则将不会保存 Spell.csx 外部正在使用的 Newtonsoft.Json 声明。换言之,如果未在 REPL 窗口中重新进行显式声明,使用 Spell.csx 内的 Newtonsoft.Json 将不会保存到 REPL 窗口(反之亦然)。请注意,也支持使用静态声明的 C# 6.0。因此,"使用静态 System.Console"声明无需将任何 System.Console 成员添加为类型的前缀,支持 REPL 命令,如"WriteLine("Hello! My name is Inigo Montoya")"。
C# 脚本中注释的其他构造包括属性使用、使用语句、属性和函数声明,以及支持 async/await。鉴于后者支持,它甚至可以在 REPL 窗口中利用 await:
(await Spell.CheckAsync("entrepreneur")).IsCorrect
以下是有关 C# REPL 界面的更多注意事项:
- 您不可从 Windows PowerShell 集成脚本编写环境 (ISE) 运行 csi.exe,因为它需要直接控制台输入,而 Windows PowerShell ISE 的"模拟"控制台不支持此操作。(因此,请考虑添加到控制台应用程序的不受支持的列表中—$psUnsupportedConsoleApplications。)
- 不存在离开 CSI 程序的"exit"或"quit"命令。但是,您可以使用 Ctrl+C 结束程序。
- 命令历史记录保存在从同一 cmd.exe 或 PowerShell.exe 会话启动的 csi.exe 会话之间。例如,如果您启动 csi.exe,调用 Console.WriteLine("HelloWorld"),使用 Ctrl+C 退出,然后重新启动 csi.exe,向上箭头键将显示上一个 Console.WriteLine("HelloWorld") 命令。退出 cmd.exe 窗口然后重新启动它将会消除历史记录。
- Csi.exe 支持 #help REPL 命令,这会显示图 3 所示的输出。
- Csi.exe 支持一些命令行选项,如图 4 所示。
图 3 REPL #help 命令输出
> #help
Keyboard shortcuts:
Enter If the current submission appears to be complete, evaluate it.
Otherwise, insert a new line.
Escape Clear the current submission.
UpArrow Replace the current submission with a previous submission.
DownArrow Replace the current submission with a subsequent
submission (after having previously navigated backward).
REPL commands:
#help Display help on available commands and key bindings.
图 4 Csi.exe 命令行选项
Microsoft (R) Visual C# Interactive Compiler version 1.1.0.51014
Copyright (C) Microsoft Corporation. All rights reserved.
Usage: csi [option] ... [script-file.csx] [script-argument] ...
Executes script-file.csx if specified, otherwise launches an interactive REPL (Read Eval Print Loop).
Options:
/help Display this usage message (alternative form: /?)
/i Drop to REPL after executing the specified script
/r:<file> Reference metadata from the specified assembly file
(alternative form: /reference)
/r:<file list> Reference metadata from the specified assembly files
(alternative form: /reference)
/lib:<path list> List of directories where to look for libraries specified
by #r directive (alternative forms: /libPath /libPaths)
/u:<namespace> Define global namespace
using
(alternative forms: /using, /usings, /import, /imports)
@<file> Read response file for more options
-- Indicates that the remaining arguments should not be
treated as options
正如前面所说,csi.exe 允许您指定可自定义命令窗口的默认"profile"文件。
- 要消除 CSI 控制台,请调用 Console.Clear。(考虑使用静态 System.Console 声明来添加支持以简化调用 Clear。)
- 如果您要输入多行命令且在之前行中出现错误,您可以使用 Ctrl+Z 然后使用 Enter 以取消并返回未执行的空命令提示符(注意,^Z 将在控制台中显示)。
Visual Studio C# 交互窗口
如上所述,Update 1 中也有全新的 Visual Studio C# 交互窗口,如图 5 所示。C# 交互窗口从"查看 | 其他窗口 | C#"交互菜单启动,打开了一个附加停靠窗口。如同 csi.exe 窗口,它是一个 C# REPL 窗口,但具有一些添加的功能。首先,它包括语法颜色编码和 IntelliSense。同样,编译在编辑时会实时发生,因此语法错误等将自动加上红色波浪下划线。
图 5 使用 Visual Studio C# 交互窗口在类外声明 C# 脚本函数
当然,与 C# 交互窗口的通常关联是 Visual Studio Immediate 和命令窗口。尽管存在重叠部分—但它们都是您可执行 .NET 语句的 REPL 窗口—它们的用途存在巨大差异。C# Immediate 窗口直接绑定到您应用程序的调试上下文,从而允许您将其他语句注入上下文,检查调试会话中的数据,甚至操作和更新数据和调试上下文。同样,命令窗口提供了一个用于操作 Visual Studio 的 CLI,包括执行各种菜单,不过是从命令窗口而不是从菜单自身。(例如,执行命令 View.C#Interactive 将会打开 C# 交互窗口。)
相反,C# 交互窗口允许您执行 C#,包括与上一部分所讨论 C# REPL 界面相关的所有功能。但是,C# 交互窗口无权访问调试上下文。它是完全独立的 C# 会话,没有调试上下文的句柄,甚至对于 Visual Studio 也没有。如同 csi.exe,这个环境无需启动另一个 Visual Studio 控制台或单元测试项目即可让您体验快速 C# 和 .NET 代码段以确认您的理解。无需启动单独的程序,但是 C# 交互窗口托管在 Visual Studio 中,开发者可能已驻留其中。
以下是一些关于 C# 交互窗口的注意事项:
- C# 交互窗口支持许多 csi.exe 中未找到的其他 REPL 命令,包括:
- #cls/#clear,可清除编辑器窗口的内容
- #reset,可将执行环境还原到初始状态,同时保持命令历史记录
- 键盘快捷方式有点出乎意料,如图 6 显示的 #help 输出。
图 6 C# 交互窗口的键盘快捷方式
输入 |
如果当前提交似乎完整,则对其进行评估。否则,插入新行。 |
Ctrl+Enter |
在当前提交内,评估当前提交。 |
Shift+Enter |
插入新行。 |
Escape |
清除当前提交。 |
Alt+UpArrow |
将当前提交替换为上一提交。 |
Alt+DownArrow |
将当前提交替换为随后的提交(之前执行了向后导航后)。 |
Ctrl+Alt+UpArrow |
将当前提交替换为以相同文本开始的上一提交。 |
Ctrl+Alt+DownArrow |
将当前提交替换为以相同文本开始的随后的提交(之前执行了向后导航后)。 |
UpArrow |
在当前提交末尾,将当前提交替换为上一提交。 在其他位置,将游标上移一行。 |
DownArrow |
在当前提交末尾,将当前提交替换为随后的提交(之前执行了向后导航后)。 在其他位置,将游标下移一行。 |
Ctrl+K、Ctrl+Enter |
在交互缓冲区末尾粘贴选择,在输入末尾保留插入点。 |
Ctrl+E、Ctrl+Enter |
在交互缓冲区中任何挂起输入之前,粘贴并执行选择。 |
Ctrl+A |
第一次按下,选择包含游标的提交。第二次按下,选择窗口中的所有文本。 |
请注意,Alt+UpArrow/DownArrow 是撤回命令历史记录的快捷键。Microsoft 选择这些而非更简单的 UpArrow/DownArrow,是因为它希望交互窗口体验符合标准 Visual Studio 代码窗口。
- 因为 C# 交互窗口托管在 Visual Studio 内,所以没有相同的机会使用声明来传递引用,或通过命令行导入,如 csi.exe 一样。但是,C# 交互窗口可从 C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\PrivateAssemblies\CSharpInteractive.rsp 加载其默认的执行上下文,这会默认识别要引用的程序集:
# This file contains command-line options that the C# REPL
# will process as part of every compilation, unless
# "/noconfig" option is specified in the reset command.
/r:System
/r:System.Core
/r:Microsoft.CSharp
/r:System.Data
/r:System.Data.DataSetExtensions
/r:System.Xml
/r:System.Xml.Linq
SeedUsings.csx
此外,CSharpInteractive.rsp 文件引用默认的 C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\PrivateAssemblies\SeedUsings.csx 文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
正是这两个文件的组合使您可以使用 Console.WriteLine 和 Environment.CurrentDirectory,而不是分别使用完全限定的 System.Console.WriteLine 和 System.Environ-ment.CurrentDirectory。此外,引用 Microsoft.CSharp 等程序集可支持使用语言功能(如动态语言),无需其他操作。(修改这些文件可更改您的"配置文件"或"首选项",使更改保存在会话之间。)
有关 C# 脚本语法的更多信息
有关 C# 脚本语法的一个注意事项是,对标准 C# 而言很重要的许多繁琐程序变成了 C# 脚本中适当的可选项。例如,方法体无需出现在函数中,且可以在类范围之外声明 C# 脚本函数。例如,您可以定义在 REPL 窗口中直接显示的 NuGet Install 函数,如图 5 所示。此外,也许有点奇怪,C# 脚本不支持声明命名空间。例如,您无法将拼写类包装在语法命名空间中:命名空间 Grammar { class Spell {} }。
请注意,您可以反复声明相同的构造(变量、类、函数等)。最新声明会覆盖早期声明。
另一个重要注意事项是命令结束分号的行为。语句(如变量分配)需要分号。没有分号,REPL 窗口将继续提示(通过句点)进行更多输入,直到输入分号。另一方面,表达式将在没有分号的情况下执行。因此,System.Diagnostics.Process.Start("记事本")将启动记事本,即使没有结束分号。此外,因为 Start 方法调用会返回进程,表达式的字符串输出将显示在命令行上:[System.Diagnostics.Process (Notepad)]。但是,使用分号结束表达式会隐藏输出。因此使用结束分号调用 Start 将不会生成任何输出,即使记事本仍将启动。当然,Console.WriteLine("It would take a miracle."); 仍将输出文本,即使带有分号,因为方法自身将显示输出(而非从方法返回)。
表达式和语句之间的差异有时可能导致细微差别。例如,statement string text = "There's a shortage of perfect b…."; 将导致无输出,但 text="Stop that rhyming and I mean it" 将返回分配的字符串(因为分配会返回已分配的值,且没有分号限制输出)。
用于引用附加程序集 (#r) 和导入现有 C# 脚本 (#load) 的 C# 脚本指令是非常出色的附加功能。(可以想像 project.json 文件等复杂解决方案实现相同的功能,这不会是件高雅的事情。)
不幸的是,编写本文时尚不支持 NuGet 包。要从 NuGet 引用文件,需要将包安装到目录,然后通过 #r 指定引用特定 DLL。(我确信 Microsoft 将会实现这一点。)
请注意,当前指令引用特定文件。例如,您无法在指令中指定变量。尽管您希望通过指令实现此操作,但它无法动态加载程序集。例如,您可以动态调用"nuget.exe install"以提取程序集(再次参见图 5)。但是,这样不会允许将您的 CSX 文件动态绑定到已提取的 NuGet 包,因为无法将程序集路径动态传递给 #r 指令。
C# CLI
我承认我对 Windows PowerShell 爱恨交加。我喜欢命令行上具有 Microsoft .NET Framework 的方便以及可以在管道中传递 .NET 对象,但我不喜欢之前 CLI 中的许多传统文本。即便如此,当涉及到 C# 语言时,我由衷地喜爱它的简洁和强大功能。(至今,我仍对使 LINQ 成为现实的语言扩展印象深刻。)
因此,我应将 Windows PowerShell .NET 的广度与 C# 语言的简洁相结合的想法,意味着我将 C# REPL 作为 Windows PowerShell 的替代品。启动 csi.exe 后,我立即尝试了 cd、dir、ls、pwd、cls、alias 等命令。一言以蔽之,我非常失望,因为这些命令均无法使用。思考体验并与 C# 团队对其进行讨论后,我意识到对于版本 1,团队关注的重点不是替换 Windows PowerShell,而是关注 .NET Framework,因此通过为前面的命令添加您自己的函数,甚至可通过在 Roslyn 上更新 C# 脚本实施,均可支持扩展性。我立即着手为这些命令定义函数。此库的入门教程可从 GitHub 下载:github.com/CSScriptEx。
对于想要寻找功能更强大的 C# CLI(可支持现已可用的先前命令列表)的用户,请考虑 scriptcs.net 上的 ScriptCS(也可从 github.com/scriptcs 的 GitHub 上获得)。它也利用 Roslyn 并包含 alias、cd、clear、cwd、exit、help、install、references、reset、scriptpacks、usings 和 vars。请注意,通过 ScriptCS,命令前缀现在是冒号(如 :reset)而非数字记号(如 #reset)。作为额外奖励,ScriptCS 也以着色和 IntelliSense 形式为 Visual Studio Code 添加了 CSX 文件支持。
总结
至少现在,C# REPL 界面的目的不是替换 Windows PowerShell 甚或 cmd.exe。要想在开始时实现此目的,将会导致失望。当然,我建议您尽可能使 C# 脚本和 REPL CLI 实现 Visual Studio | 新项目的轻型替换: UnitTestProject105 或目的相似的 dotnetfiddle.net。这些是面向 C# 和 .NET 的方法,用于加强您对语言和 .NET API 的理解。C# REPL 提供了对短代码段或程序单元进行编码的方式,您可以即兴使用,直到它们已被剪切并粘贴到大型程序中。它允许您在写入代码时写入语法已验证的更广泛脚本(即便存在大小写不匹配这样的小问题),而不会强制您仅执行脚本以发现输入错误的内容。一旦您知道它的位置,C# 脚本及其交互窗口会变得乐趣无穷,这正是自版本 1.0 起您一直期待的工具。
如同 C# REPL 和 C# 脚本自身一样有趣,认为它们也为成为您自己应用程序的扩展框架提供了跳板—仿照 Visual Basic for Applications (VBA)。通过交互窗口和 C# 脚本支持,您可以想像一个世界—不是太遥远—在这个世界里,您可以将 .NET"宏"再次添加到自己的应用程序中,而无需创建自定义语言、分析器和编辑器。现在,传统 COM 功能正是时候值得引领我们走向新世界。
Mark Michaelis 是 IntelliTect 的创始人,担任首席技术架构师和培训师。在近二十年的时间里,他一直是 Microsoft MVP,并且自 2007 年以来一直担任 Microsoft 区域总监。Michaelis 还是多个 Microsoft 软件设计评审团队(包括 C#、Microsoft Azure、SharePoint 和 Visual Studio ALM)的成员。他在开发者会议上发表了演讲,并撰写了大量书籍,包括最新的"必备 C# 6.0(第 5 版)"(itl.tc/EssentialCSharp)。可通过他的 Facebook facebook.com/Mark.Michaelis、博客 IntelliTect.com/Mark、Twitter @markmichaelis 或电子邮件 mark@IntelliTect.com 与他取得联系。
衷心感谢以下 Microsoft 技术专家对本文的审阅: Kevin Bost 和 Kasey Uhlenhuth
必备 .NET - C# 脚本的更多相关文章
- Python自动化必备发送邮件报告脚本详解
#!/usr/bin/python3# -*- coding:UTF-8 -*-import smtplib#smtplib库主要用来连接第三方smtp库,用来发邮件from email.mime.t ...
- 运维工程师打怪升级进阶之路 V2.0
在此之前,发布过两个版本: 运维工程师打怪升级之路 V1.0 版本发布 运维工程师打怪升级必经之路 V1.0.1 很多读者伙伴们反应总结的很系统.很全面,无论是0基础初学者,还是有基础的入门者,或者是 ...
- 「SpringBoot」如何优雅地管理SpringBoot项目
本文主要讲述一下如何优雅地管理SpringBoot项目. 背景 课堂上,当小明形如流水地回答完沐芳老师提出来的问题时,却被至今没有对象的胖虎无情嘲讽了? 沐芳老师:小明,你平时是如何启动.停止你的Sp ...
- 【风哥干货】快速解决Oracle数据库故障必备的20个脚本与命令
1.操作系统性能(通常故障出现时最先检查的内容)top.topas.vmstat.iostat.free.nmon 2.万能重启方法 如应急情况,需要重启数据库:tail -100f <对应路径 ...
- 测试必备技能系列1 :通过mysql命令进行脚本数据导入
老徐,分享测试项目中实际能解决问题的干货! 今日分享: 如何通过mysql命令行,导入mysql脚本文件数据? ----- 解决实际的问题: 工作过程中,经常需要导入mysql脚本文件 很多同 ...
- 真正菜鸟用教程之WQSG Scrip Export WQSG (脚本导出导入工具,PSP、NDS汉化必备 )
先扫盲WQSG是干什么用的 一些掌机类游戏汉化比方PSP NDS 汉化必备之物 它能够依据字典转换文本 假设你不知道这是啥玩意,快去充电染成茜色的坂道 文本提取(导出)方法 (下文称导出文章) 在导出 ...
- 程序员(媛)Shell脚本必备技能之中的一个: 在Linux下怎样自己主动备份mysql数据
作者:荀彧(花名) Background:鉴于QAS数据库曾遭到毁灭性损害.极其桑心L.为了避免这样的玉石俱焚的状况再度发生.于是我们找出了一种应对方案.这里给大家分享一下怎样实现定时备份mysql数 ...
- 分享7个shell脚本实例--shell脚本练习必备
概述 看多shell脚本实例自然就会有shell脚本的编写思路了,所以我一般比较推荐看脚本实例来练习shell脚本.下面分享几个shell脚本实例. 1.监测Nginx访问日志502情况,并做相应动作 ...
- shell 脚本之判断语句 if 详解
使用 Linux 系统这么长时间,对 shell 脚本也算是比较熟悉.其实不管是搞开发,还是搞运维,shell 脚本都是必备的基本技能.这次抽时间好好总结一下 shell 方面的知识,综合的再学习一下 ...
随机推荐
- 浅谈fhq_treap
\(BST\) 二叉查找树,首先它是一颗二叉树,其次它里面每个点都满足以该点左儿子为根的子树里结点的值都小于自己的值,以该点右儿子为根的子树里结点的值都大于自己的值.如果不进行修改,每次查询都是\(O ...
- vue-router 结合源码分析原理
路由响应过程: 浏览器发出请求 服务器监听到num端口(或443)有请求过来,并解析url路径 根据服务器的路由配置,返回相应信息(可以是 html 字串,也可以是 json 数据,图片等) 浏览器根 ...
- 利用windows server 2012 R2的Hyper-V搭建多个虚拟机的 Dynamics CRM 环境知识点小结
一.需要掌握网络的知识,域真正的意义,防火墙等其他知识,这些知识我还需要加强,下面是我和同事的结果,不对的地方大家可以指出来,谢谢. 1.安装好的CRM2011环境,必须先打Update Rollup ...
- IplImage的数据结构以及遍历方法
一般我们需要对图像直接进行操作的时候,需要知道图像存储的数据结构,这要也就知道了它的遍历方式 在opencv2.4.4版本下,IplImage的数据结构如下(貌似在别的版本下差别也不会太大) 其中比较 ...
- Pascal可视化编程 CodeTyphon 、Lazarus
CodeTyphon是一个免费的Pascal语言可视化编程工作室软件包,基于Free Pascal和Lazarus.相当于Delphi 的RAD Studio. CodeTyphon支持多平台开发,包 ...
- 远程连接linux服务器mysql
今天遇到一个问题 无法远程链接mysql Host 'XXX' is not allowed to connect to this MySQL server 解决方案/如何开启MySQ先解决第一个提 ...
- JVM插码之五:Java agent+ASM实战--监控所有方法执行时间
本文建立在对instrumentation和agent有初步的了解的前提下阅读,关于这2个类的讲解在其它文章中. 这是一个maven项目,pom中需要的配置,lib中有asm的jar包 pom.xml ...
- 杂项:ORM
ylbtech-杂项:ORM 对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不 ...
- selenium Java-1 配置
1.使用intellij新建一个maven项目,名字自定.在pom中写入selenium的依赖.其他依赖也添加到该文件中. [maven selenium依赖](http://mvnreposit ...
- ROS-RouterOS 的license注册级别
原文: https://wiki.mikrotik.com/wiki/Manual:CHR#CHR_Licensing https://wiki.mikrotik.com/wiki/Manual:Li ...