#Script is a simple, fast, highly versatile and embeddable scripting language for .NET Core and .NET Apps that utilizes a familiar JavaScript inspired expressive Syntax to enable dynamic scripting of .NET Apps via controlled access to pluggable methods and arguments within a sandbox environment - ensuring scripts are encapsulated and encourages the use of reusable and testable components where live environments can be easily re-created and simulated.
مجموعه آیکن های وب با کیفیت بالا
تغییرات گسترده در EF Core 3x
In an attempt to correct many perceived deficiencies in Entity Framework Core, Microsoft is introducing 40 breaking changes to EF Core 3. You can see the entire breaking changes list on Microsoft Docs, but here are some of the highlights.
URL ها رابط کاربری (UI) هستند
Extended Events/Trace
Extended Events، زیر ساخت مدیریت رخدادها در SQL Server است. برای مثال در نگارش 2016 آن بیشاز 300 رخداد در SQL Server تعریف شدهاند و زمانیکه در مورد اجرای کوئریها بحث میکنیم، این رخدادها بیشتر مدنظر ما هستند:
sql_statement_completed sp_statement_completed rpc_completed sql_batch_completed
علاوه بر اینها، رخدادهای بسط یافتهی زیر را نیز میتوان مورد استفاده قرار داد:
query_post_compilation_showplan query_post_execution_showplan query_pre_execution_showplan
استفاده از Extended Events برای جمع آوری اطلاعات آماری کوئریها
برای آزمایش نحوهی کار با Extended Events، ابتدا رویهی ذخیره شدهی زیر را ایجاد میکنیم:
USE [WideWorldImporters]; GO DROP PROCEDURE IF EXISTS [Application].[usp_GetCountryInfo]; GO CREATE PROCEDURE [Application].[usp_GetCountryInfo] @Country_Name NVARCHAR(60) AS SELECT * FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = @Country_Name; GO
سپس یک سشن Extended Events سفارشی را به صورت زیر ایجاد میکنیم:
/* Create XE session to capture sql_statement_completed and sp_statement_completed */ IF EXISTS ( SELECT * FROM sys.server_event_sessions WHERE [name] = 'QueryPerf') BEGIN DROP EVENT SESSION [QueryPerf] ON SERVER; END GO CREATE EVENT SESSION [QueryPerf] ON SERVER ADD EVENT sqlserver.sp_statement_completed(WHERE ([duration]>(1000))), ADD EVENT sqlserver.sql_statement_completed(WHERE ([duration]>(1000))) ADD TARGET package0.event_file(SET filename=N'C:\Temp\QueryPerf\test.xel',max_file_size=(256)) WITH ( MAX_MEMORY=16384 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF); GO
سپس نیاز است تا این سشن را که QueryPerf نام دارد، در قسمت management->extended events، اجرا و آغاز کرد:
در ادامه ابتدا بر روی بانک اطلاعاتی WideWorldImporters، کلیک راست کرده و یک پنجرهی new query جدید را ایجاد میکنیم:
WHILE 1 = 1 BEGIN EXECUTE [Application].[usp_GetCountryInfo] N'United States'; END
سپس مجددا یک پنجرهی new query دیگر را باز میکنیم:
WHILE 1 = 1 BEGIN SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = 'United States'; END
کوئریهای هر دو پنجره را به صورت مجزایی اجرا کنید. سپس در قسمت management->extended events، بر روی سشن QueryPerf کلیک راست کرده و گزینهی View live data را انتخاب کنید:
این زندهترین خروجی یک سشن رخدادهای بسط یافتهاست. کار کردن با آن نسبت به روشی که در قسمت قبل بررسی کردیم، سادهتر و سریعتر است و همچنین گزارش آن به صورت خودکار تولید میشود.
یک نکته: در اینجا در قسمت Details، اگر بر روی هر ردیف کلیک کنید، امکان انتخاب و نمایش آن در لیست بالای صفحه توسط گزینهی Show Column in table وجود دارد.
در آخر در قسمت management->extended events، بر روی سشن QueryPerf کلیک راست کرده و گزینهی Stop Session را انتخاب کنید. اکنون اگر به پوشهی C:\Temp\QueryPerf مراجعه کنید، فایل xel حاوی اطلاعات این گزارش را نیز میتوانید مشاهده نمائید (به ازای هربار اجرای این سشن، یک فایل جدید را تولید میکند).
این فایل توسط Management Studio قابل گشودن و بررسی است و دقیقا همان نمای گزارش live data را به همراه دارد.
Firefox 70 و پیشنهاد کلمهی عبور امن
These are the customer-reported issues addressed in 15.7.3:
- VS2017 compiler creates broken debug build using Qt framework and generates 'Invalid address specified to RtlValidateHeap' error.
- Incorrect code generation for matrix multiplication.
- VS 2017 Update 7: Git History Codelens only showing entries for the past 6 months.
- UWP projects reference multiple NetStandard 2.0 dlls after 15.7.1 upgrade.
- Building C++ code in VS 15.7 with /std:c++17 breaks binary compatibility for std::_Ptr_move_cat.
- Visual Studio 15.7 stuck when opening XAML files.
- CMake configuration fails and generates message "C++ IntelliSense information may be out of date, generate the CMake cache to refresh".
- Unable to start second process for debugging.
- After update to Visual Studio 15.7.1, some test programs fail in start-up due to reading access violation.
- Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.Binder.Convert'.
- Build fails after 15.7.0 update on older project using .NET 3.5 .
- Coloring, typing, tooltips and IntelliSense slow in F# in VS2017 editor.
- F# editing experience takes up to a minute for tooltips and dropdowns to display.
- Certain class member variable value are incorrectly read as zero.
- Attempt to open XAML file for the first time causes VS to sit with the "Opening the file ..." message for about 10 minutes before XAML file opens.
- Visual Studio slows down and freezes, creating work loss.
- The target "GetBuiltProjectOutputRecursive" does not exist in the project.
- Internal error with lambda C++17 after 15.7.1 update.
- UWP App is slow to return a stopped state in IDE.
- MSVC auto-vectorization produces incorrect code or incorrect results.
- Visual Studio closed debug a new instance project1, when a new debug new instance project2 has started.
- Latest update breaks "start without debugging" on multiple projects.
- UWP XAML is very very slow on open.
- XAML viewer freezes on 15.7.2 and 15.8.0 preview 1.1.
- Xamarin UI Test App project template missing.
- Xamarin project creation problem.
- Visual Studio crashes when creating new Mobile APP Xamarin.
- Unable to create Xamarin.Forms-Projects.
- Não consigo criar novos projetos Xamarin Forms - Can't create new projects Xamarin Forms.
- Blank project crash after update.
PATINDEX ( '%pattern%' , expression )
- لازم است در آرگومان اول حداقل یک % وجود داشته باشد.
- حداکثر تعداد کاراکترهایی را که میتوان در آرگومان اول قرار داد 8000 میباشد.
- اگر تعداد کارکترهای آرگومان دوم (Varchar(Max یا (nVarchar(Max باشد، در آن صورت Type خروجی تابع PATINDEX از نوع bigint میباشد، در غیر این صورت Type خروجی تابع PATINDEX از نوع Int است.
- اگر مقدار آرگومان دوم Null باشد، تابع PATINDEX مقدار Null بر میگرداند.
USE tempdb GO CREATE TABLE UsingPATINDEX (ID INT, Words VARCHAR (100)) GO INSERT INTO UsingPATINDEX (ID, Words) SELECT 1, '1one' UNION ALL SELECT 2, '11eleven' UNION ALL SELECT 3, '2two' UNION ALL SELECT 4, '22twentytwo' UNION ALL SELECT 5, '111oneeleven' GO
SELECT PATINDEX('%[a-z]%',Words) 'مکان اولین کاراکتر غیر عددی', SUBSTRING(Words,PATINDEX('%[a-z]%',Words),1) 'نام اولین کاراکتر غیر عددی بعد از عدد', Words 'متن اصلی' FROM UsingPATINDEX
PATINDEX('%[a-z]%',Words) 'مکان اولین کاراکتر غیر عددی'
SUBSTRING(Words,PATINDEX('%[a-z]%',Words),1) 'نام اولین کاراکتر غیر عددی بعد از عدد'
SELECT PATINDEX('%en_ure%', 'please ensure the door is locked');
- در تابع PATINDEX میتوانید براساس Collation دلخواه عملیات جستجو را انجام دهید، برای روشتر شدن مطلب شکل زیر را مشاهده نمایید:
Select PATINDEX('a%', 'abc')
Select PATINDEX('%a', 'cba')
- باید متذکر شوم، با دیدن دو مثال آخر،این تصور ایجاد نشود که تابع PATINDEX شبیه به تابع LIKE میباشد، چرا که تابع PATINDEX موقعیت کاراکتر را بر میگرداند، نه خود کاراکتر را،عملکرد تابع PATINDEX شبیه به عملکرد تابع CHARINDEX میباشد.
Roslyn #7
Workspace، در حقیقت نمایش اجزای یک Solution در ویژوال استودیو است و یک Solution متشکل است از تعدادی پروژه به همراه وابستگیهای بین آنها. هدف از وجود Workspace API در Roslyn، دسترسی به اطلاعات لازم جهت انجام امور Refactoring در سطح یک Solution است. برای مثال اگر قرار است نام خاصیتی تغییر کند و این خاصیت در چندین پروژهی دیگر در حال استفاده است، این نام باید در سراسر Solution جاری یافت شده و تغییر یابد. همچنین برفراز Workspace API تعدادی سرویس زبان مانند فرمت کنندههای کدها، تغییرنام دهندههای سیمبلها و توصیه کنندهها نیز تهیه شدهاند.
همچنین این سرویسها و API تهیه شده، منحصر به ویژوال استودیو نیستند و VS 2015 تنها از آنها استفاده میکند. برای مثال نگارشهای جدیدتر mono-develop لینوکسی نیز شروع به استفادهی از Roslyn کردهاند.
نمایش اجزای یک Solution
در ادامه مثالی را مشاهده میکنید که توسط آن نام Solution و سپس تمام پروژههای موجود در آنها به همراه نام فایلهای مرتبط و همچنین ارجاعات آنها در صفحه نمایش داده میشوند:
var ws = MSBuildWorkspace.Create(); var sln = ws.OpenSolutionAsync(@"..\..\..\Roslyn.sln").Result; // Print the root of the solution. Console.WriteLine(Path.GetFileName(sln.FilePath)); // Get dependency graph to perform a sort. var g = sln.GetProjectDependencyGraph(); var ps = g.GetTopologicallySortedProjects(); // Print all projects, their documents, and references. foreach (var p in ps) { var proj = sln.GetProject(p); Console.WriteLine("> " + proj.Name); Console.WriteLine(" > References"); foreach (var r in proj.ProjectReferences) { Console.WriteLine(" - " + sln.GetProject(r.ProjectId).Name); } foreach (var d in proj.Documents) { Console.WriteLine(" - " + d.Name); } }
Roslyn.sln > Roslyn01 > References - Program.cs - AssemblyInfo.cs - .NETFramework,Version=v4.6.AssemblyAttributes.cs
ایجاد یک Syntax highlighter با استفاده از Classification service
هدف از Classification service، رندر کردن فایلها در ادیتور جاری است. برای این منظور نیاز است بتوان واژههای کلیدی، کامنتها، نامهای نوعها و امثال آنها را به صورت کلاسه شده در اختیار داشت و سپس برای مثال هرکدام را با رنگی مجزا نمایش داد و رندر کرد.
در ادامه مثالی از آنرا ملاحظه میکنید:
var ws = MSBuildWorkspace.Create(); var sln = ws.OpenSolutionAsync(@"..\..\..\Roslyn.sln").Result; // Get the Tests\Bar.cs document. var proj = sln.Projects.Single(p => p.Name == "Roslyn04.Tests"); var test = proj.Documents.Single(d => d.Name == "Bar.cs"); var tree = test.GetSyntaxTreeAsync().Result; var root = tree.GetRootAsync().Result; // Get all the spans in the document that are classified as language elements. var spans = Classifier.GetClassifiedSpansAsync(test, root.FullSpan).Result.ToDictionary(c => c.TextSpan.Start, c => c); // Print the source text with appropriate colorization. var txt = tree.GetText().ToString(); var i = 0; foreach (var c in txt) { var span = default(ClassifiedSpan); if (spans.TryGetValue(i, out span)) { var color = ConsoleColor.Gray; switch (span.ClassificationType) { case ClassificationTypeNames.Keyword: color = ConsoleColor.Cyan; break; case ClassificationTypeNames.StringLiteral: case ClassificationTypeNames.VerbatimStringLiteral: color = ConsoleColor.Red; break; case ClassificationTypeNames.Comment: color = ConsoleColor.Green; break; case ClassificationTypeNames.ClassName: case ClassificationTypeNames.InterfaceName: case ClassificationTypeNames.StructName: case ClassificationTypeNames.EnumName: case ClassificationTypeNames.TypeParameterName: case ClassificationTypeNames.DelegateName: color = ConsoleColor.Yellow; break; case ClassificationTypeNames.Identifier: color = ConsoleColor.DarkGray; break; } Console.ForegroundColor = color; } Console.Write(c); i++; }
توضیحات:
در اینجا نیز کار با ایجاد یک Workspace و سپس گشودن Solution ایی مشخص در آن آغاز میشود. سپس در آن به دنبال پروژهای به نام Roslyn04.Tests میگردیم. این پروژه حاوی تعدادی کلاس، جهت بررسی و آزمایش هستند. برای مثال در اینجا فایل Bar.cs آن قرار است آنالیز شود. پس از یافتن آن، ابتدا syntax tree آن دریافت میگردد و سپس به سرویس Classifier.GetClassifiedSpansAsync ارسال خواهد شد. خروجی آن شامل لیستی از Classified Spans است؛ مانند کلمات کلیدی، رشتهها، کامنتها و غیره. در ادامه این لیست تبدیل به یک دیکشنری میشود که کلید آن محل آغاز این span و مقدار آن، مقدار span است. سپس متن syntax tree دریافت شده و حرف به حرف آن در طی یک حلقه بررسی میشود. در این حلقه، مقدار i به محل حروف جاری مورد آنالیز اشاره میکند. اگر این محل در دیکشنری Classified Spans وجود داشت، یعنی یک span جدید شروع شدهاست و بر این اساس، نوع آن span را میتوان استخراج کرد و سپس بر اساس این نوع، رنگ متفاوتی را در صفحه نمایش داد.
سرویس فرمت کردن کدها
این سرویس کار فرمت خودکار کدهای بهم ریخته را انجام میدهد؛ مانند تنظیم فاصلههای خالی و یا ایجاد indentation و امثال آن. در حقیقت Ctlr K+D در ویژوال استودیو، دقیقا از همین سرویس زبان استفاده میکند.
کار کردن با این سرویس از طریق برنامه نویسی به نحو ذیل است:
var ws = MSBuildWorkspace.Create(); var sln = ws.OpenSolutionAsync(@"..\..\..\Roslyn.sln").Result; // Get the Tests\Qux.cs document. var proj = sln.Projects.Single(p => p.Name == "Roslyn04.Tests"); var qux = proj.Documents.Single(d => d.Name == "Qux.cs"); Console.WriteLine("Before:"); Console.WriteLine(); Console.WriteLine(qux.GetSyntaxTreeAsync().Result.GetText()); Console.WriteLine(); Console.WriteLine(); // Apply formatting and print the result. var res = Formatter.FormatAsync(qux).Result; Console.WriteLine("After:"); Console.WriteLine(); Console.WriteLine(res.GetSyntaxTreeAsync().Result.GetText()); Console.WriteLine();
Before: using System; namespace Roslyn04.Tests { class Qux { public void Baz() { Console.WriteLine(42); return; } } } After: using System; namespace Roslyn04.Tests { class Qux { public void Baz() { Console.WriteLine(42); return; } } }
سرویس یافتن سیمبلها
یکی دیگر از قابلیتهایی که در ویژوال استودیو وجود دارد، امکان یافتن سیمبلها است. برای مثال این نوع یا کلاس خاص، در کجاها استفاده شدهاست و به آن ارجاعاتی وجود دارد. مواردی مانند Find all references، Go to definition و نمایش Call hierarchy از این سرویس استفاده میکنند.
var ws = MSBuildWorkspace.Create(); var sln = ws.OpenSolutionAsync(@"..\..\..\Roslyn.sln").Result; // Get the Tests project. var proj = sln.Projects.Single(p => p.Name == "Roslyn04.Tests"); // Locate the symbol for the Bar.Foo method and the Bar.Qux property. var comp = proj.GetCompilationAsync().Result; var barType = comp.GetTypeByMetadataName("Roslyn04.Tests.Bar"); var fooMethod = barType.GetMembers().Single(m => m.Name == "Foo"); var quxProp = barType.GetMembers().Single(m => m.Name == "Qux"); // Find callers across the solution. Console.WriteLine("Find callers of Foo"); Console.WriteLine(); var callers = SymbolFinder.FindCallersAsync(fooMethod, sln).Result; foreach (var caller in callers) { Console.WriteLine(caller.CallingSymbol); foreach (var location in caller.Locations) { Console.WriteLine(" " + location); } } Console.WriteLine(); Console.WriteLine(); // Find all references across the solution. Console.WriteLine("Find all references to Qux"); Console.WriteLine(); var references = SymbolFinder.FindReferencesAsync(quxProp, sln).Result; foreach (var reference in references) { Console.WriteLine(reference.Definition); foreach (var location in reference.Locations) { Console.WriteLine(" " + location.Location); } }
اکنون با استفاده از سرویس SymbolFinder.FindCallersAsync تمام فراخوانهای متد Foo را در سراسر Solution جاری مییابیم.
سپس با استفاده از سرویس SymbolFinder.FindReferencesAsync تمام ارجاعات به خاصیت Qux را در Solution جاری نمایش میدهیم.
سرویس توصیه کننده
Intellisense در ویژوال استودیو از سرویس توصیه کنندهی Roslyn استفاده میکند.
var ws = MSBuildWorkspace.Create(); var sln = ws.OpenSolutionAsync(@"..\..\..\Roslyn.sln").Result; // Get the Tests\Foo.cs document. var proj = sln.Projects.Single(p => p.Name == "Roslyn04.Tests"); var foo = proj.Documents.Single(d => d.Name == "Foo.cs"); // Find the 'dot' token in the first Console.WriteLine member access expression. var tree = foo.GetSyntaxTreeAsync().Result; var model = proj.GetCompilationAsync().Result.GetSemanticModel(tree); var consoleDot = tree.GetRoot().DescendantNodes().OfType<MemberAccessExpressionSyntax>().First().OperatorToken; // Get recommendations at the indicated cursor position. // // Console.WriteLine // ^ var res = Recommender.GetRecommendedSymbolsAtPosition( model, consoleDot.GetLocation().SourceSpan.Start + 1, ws).ToList(); foreach (var rec in res) { Console.WriteLine(rec); }
تعدادی از خروجیهای مثال فوق به صورت زیر هستند:
System.Console.Beep() System.Console.Beep(int, int) System.Console.Clear()
سرویس تغییر نام دادن
هدف از سرویس Renamer.RenameSymbolAsync، تغییر نام یک identifier در کل Solution است. نمونهای از نحوهی کاربرد آنرا در مثال ذیل مشاهده میکنید:
var ws = MSBuildWorkspace.Create(); var sln = ws.OpenSolutionAsync(@"..\..\..\Roslyn.sln").Result; // Get Tests\Bar.cs before making changes. var oldProj = sln.Projects.Single(p => p.Name == "Roslyn04.Tests"); var oldDoc = oldProj.Documents.Single(d => d.Name == "Bar.cs"); Console.WriteLine("Before:"); Console.WriteLine(); var oldTxt = oldDoc.GetTextAsync().Result; Console.WriteLine(oldTxt); Console.WriteLine(); Console.WriteLine(); // Get the symbol for the Bar.Foo method. var comp = oldProj.GetCompilationAsync().Result; var barType = comp.GetTypeByMetadataName("Roslyn04.Tests.Bar"); var fooMethod = barType.GetMembers().Single(m => m.Name == "Foo"); // Perform the rename. var newSln = Renamer.RenameSymbolAsync(sln, fooMethod, "Foo2", ws.Options).Result; // Get Tests\Bar.cs after making changes. var newProj = newSln.Projects.Single(p => p.Name == "Roslyn04.Tests"); var newDoc = newProj.Documents.Single(d => d.Name == "Bar.cs"); Console.WriteLine("After:"); Console.WriteLine(); var newTxt = newDoc.GetTextAsync().Result; Console.WriteLine(newTxt);
سرویس ساده کننده
هدف از سرویس ساده کننده، سادهکردن و کاهش کدهای ارائه شده، از دید Semantics است. برای مثال اگر فضای نامی در قسمت using ذکر شدهاست، دیگر نیازی نیست تا این فضای نام به ابتدای فراخوانی یک متد آن اضافه شود و میتوان این قطعه از کد را سادهتر کرد و کاهش داد.
var ws = MSBuildWorkspace.Create(); var sln = ws.OpenSolutionAsync(@"..\..\..\Roslyn.sln").Result; // Get the Tests\Baz.cs document. var proj = sln.Projects.Single(p => p.Name == "Roslyn04.Tests"); var baz = proj.Documents.Single(d => d.Name == "Baz.cs"); Console.WriteLine("Before:"); Console.WriteLine(); Console.WriteLine(baz.GetSyntaxTreeAsync().Result.GetText()); Console.WriteLine(); Console.WriteLine(); var oldRoot = baz.GetSyntaxRootAsync().Result; var memberAccesses = oldRoot.DescendantNodes().OfType<CastExpressionSyntax>(); var newRoot = oldRoot.ReplaceNodes(memberAccesses, (_, m) => m.WithAdditionalAnnotations(Simplifier.Annotation)); var newDoc = baz.WithSyntaxRoot(newRoot); // Invoke the simplifier and print the result. var res = Simplifier.ReduceAsync(newDoc).Result; Console.WriteLine("After:"); Console.WriteLine(); Console.WriteLine(res.GetSyntaxTreeAsync().Result.GetText()); Console.WriteLine();
کدهای کامل این سری را از اینجا میتوانید دریافت کنید:
Roslyn-Samples.zip