Mục lục
Giới thiệu
.NET 10 sắp ra mắt. Một trong những tính năng siêu hay của .NET 10 là bạn có thể chạy trực tiếp các file C# độc lập mà không cần tạo project.
Chạy script là cách mạnh mẽ cho các tác vụ đơn giản, nhưng cũng cho các tác vụ mà bạn chạy ví dụ như một phần của pipeline CI/CD (CI=Continuous Integration, CD=Continous Deployment). Với .NET 10, bạn có thể sử dụng C# ở nhiều nơi mà trước đây bạn từng sử dụng PowerShell hoặc bất kỳ ngôn ngữ script nào khác.
Chạy một file C#
Hãy bắt đầu với một file C# đơn giản. Trong thư mục C:\Code của tôi, tôi tạo một file Program.cs với nội dung bên dưới. Nó sẽ ghi các thư mục của ổ đĩa C: của tôi ra console.
var myDirectories = Directory.GetDirectories(@"C:\");
foreach (var dir in myDirectories)
{
Console.WriteLine(dir);
}
Bây giờ hãy sử dụng lệnh dotnet run để chạy file Program.cs này trực tiếp mà không tạo project C# rõ ràng. Để chạy lệnh này, .NET 10 hoặc mới hơn phải được cài đặt trên máy của bạn.
dotnet run Program.cs
Bên dưới bạn có thể thấy ảnh chụp màn hình cách tôi thực thi lệnh này trong cửa sổ PowerShell. Như mong đợi, nó in ra các thư mục của ổ đĩa C: của tôi.
Khá tuyệt phải không?
Nếu bạn quen với các ngôn ngữ lập trình khác cho phép bạn thực thi một file, ví dụ như Python, bạn có thể đánh giá cao rằng cách tiếp cận này giờ đây cũng có sẵn cho C# với .NET 10.
Nó hoạt động như thế nào trong Python?
Trong Python bạn có thể thực thi file theo cách tương tự. Bạn có thể tạo ví dụ một file Program.py với nội dung bên dưới làm chính xác những gì file C# từ trên – nó liệt kê các thư mục của ổ đĩa C:.
import os
for dir in os.listdir(r'C:\\'):
path = os.path.join(r'C:\\', dir)
if os.path.isdir(path):
print(path)
Với Python đã cài đặt trên máy của bạn, bạn có thể thực thi file với lệnh này:
python Program.py
Như bạn vừa học trong bài đăng blog này, với .NET 10, bạn có thể làm điều tương tự với các file C# của mình.
Còn về NuGet Packages?
Bạn cũng có thể tham chiếu các gói NuGet trong các file C# độc lập của mình với cú pháp mới có dạng:
#:package YourPackage@1.0.0
Hãy điều chỉnh file Program.cs của tôi và hãy bao gồm Serilog để ghi log, thay vì ghi trực tiếp vào console thông qua Console.WriteLine.
Đoạn code bên dưới hiển thị toàn bộ file Program.cs giờ đây sử dụng các gói NuGet Serilog và Serilog.Sinks.Console. Sau hai chỉ thị #:package, một chỉ thị using cho namespace Serilog được thêm vào, và sau đó thuộc tính tĩnh Log.Logger được khởi tạo với một logger ghi vào console.
Trong vòng lặp foreach, phương thức tĩnh Log.Information được sử dụng để ghi một thông báo cho mỗi thư mục tìm thấy. Lưu ý rằng chuỗi chứa trình giữ chỗ {Directory}, đây là một đặc điểm cụ thể của Serilog. Trình giữ chỗ có thể là bất kỳ chuỗi nào, thậm chí chỉ {blabla} cũng hoạt động. Nó được thay thế bằng nội dung của biến dir. Tất nhiên, bạn cũng có thể sử dụng chuỗi nội suy cho việc này, nhưng kết quả của trình giữ chỗ cụ thể Serilog này là phần này của thông báo log được tô sáng trong đầu ra.
#:package Serilog@4.3.0
#:package Serilog.Sinks.Console@6.0.0
using Serilog;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.CreateLogger();
var myDirectories = Directory.GetDirectories(@"C:\");
foreach (var dir in myDirectories)
{
Log.Information("Found directory: {Directory}", dir);
}
Bên dưới bạn có thể thấy đầu ra khi bạn chạy file Program.cs. Các thư mục được tô sáng bởi Serilog.
Còn về Project Properties?
Đôi khi bạn chỉ định những thứ trong file .csproj, ví dụ như phiên bản ngôn ngữ C# hoặc một .NET SDK cụ thể hơn. Bạn cũng có thể làm điều này với file C# độc lập của mình bằng cách thêm các chỉ thị vào file của bạn bắt đầu bằng #:, như các tham chiếu gói NuGet từ phần trước của bài đăng blog này bắt đầu bằng #:package.
Để tham chiếu một SDK cụ thể, ví dụ SDK Web để xây dựng một minimal API, bạn sử dụng chỉ thị #:sdk. Trong đoạn code bên dưới bạn thấy một file Program.cs chứa toàn bộ code cho một minimal API đơn giản. Lưu ý chỉ thị #:sdk ở đầu. Theo mặc định, implicit usings cũng được bật, có nghĩa là không cần chỉ thị using để sử dụng class WebApplication.
#:sdk Microsoft.NET.Sdk.Web
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello from Web API from simple C# file");
app.Run();
Khi bạn chạy file này như bên dưới, một máy chủ web khởi động và bạn có thể sử dụng Web API của mình. Không tuyệt sao?
Nó cũng có thể chỉ định các thuộc tính MSBuild khác với chỉ thị #:. Nếu bạn muốn sử dụng ví dụ phiên bản xem trước của C# trong file của bạn, bạn có thể sử dụng chỉ thị bên dưới để đặt thuộc tính LangVersion thành giá trị preview:
#:property LangVersion preview
Bạn tìm thấy nhiều chỉ thị hơn và thậm chí hỗ trợ để xây dựng shell script có thể thực thi với C# trong bài đăng blog .NET này.
Nếu bạn cần một Project File thì sao?
Bất cứ khi nào bạn đạt đến một điểm với file C# độc lập của mình mà bạn có nhu cầu cho một file .csproj, bạn có thể chạy lệnh sau để chuyển đổi file C# độc lập của bạn thành một project với file .csproj:
dotnet project convert Program.cs
Lệnh này sẽ hỏi bạn về một thư mục đầu ra cho project. Sau đó nó sẽ tạo file .csproj tương ứng cho bạn trong thư mục đầu ra đó. File .csproj này sẽ bao gồm tất cả các tham chiếu gói NuGet, thuộc tính MSBuild và SDK được chỉ định mà bạn đã bao gồm trong file C# của mình với các chỉ thị #:. Nó cũng sẽ bao gồm chính file C#, nhưng giờ đây không có các chỉ thị #:, vì tất cả thông tin đó giờ đây là một phần của file .csproj.
Hãy lấy file Program.cs bên dưới mà chúng ta đã sử dụng trong bài đăng blog này làm ví dụ.
#:package Serilog@4.3.0
#:package Serilog.Sinks.Console@6.0.0
using Serilog;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.CreateLogger();
var myDirectories = Directory.GetDirectories(@"C:\");
foreach (var dir in myDirectories)
{
Log.Information("Found directory: {Directory}", dir);
}
Trong cửa sổ console bên dưới, tôi chạy lệnh dotnet project convert cho file Program.cs. Tôi đã nhập MyProgram làm thư mục đầu ra. Tên mặc định cho thư mục sẽ là tên của file, trong trường hợp này là Program. Sau đó, tôi điều hướng vào thư mục MyProgram để liệt kê nội dung của nó với lệnh ls. Như bạn có thể thấy, một file Program.cs và một file Program.csproj đã được tạo.
File Program.csproj được tạo chứa các tham chiếu gói NuGet tương ứng cho Serilog mà tôi đã định nghĩa trong file C# với các chỉ thị #:package, như bạn có thể thấy bên dưới.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
</ItemGroup>
</Project>
File Program.cs đã được dọn dẹp và không chứa bất kỳ chỉ thị #: nào nữa. Nó trông như bên dưới.
using Serilog;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.CreateLogger();
var myDirectories = Directory.GetDirectories(@"C:\");
foreach (var dir in myDirectories)
{
Log.Information("Found directory: {Directory}", dir);
}
Điều này có nghĩa là bây giờ, trong thư mục MyProgram, bạn có thể chạy chỉ dotnet run như bạn đã có thể với các phiên bản .NET trước đó, và .NET CLI sẽ nhận file .csproj từ thư mục đó và thực thi project tương ứng file .exe được tạo từ project. Cửa sổ console bên dưới cho thấy điều này trong hành động.
Tóm tắt
Tính năng mới này của .NET 10 để thực thi file trực tiếp mà không cần file .csproj rõ ràng là rất mạnh mẽ. Nó có nghĩa là C# giờ đây là một lựa chọn siêu hợp lệ cho bất kỳ script nào mà bạn đã triển khai trước đây với PowerShell, Python hoặc bất kỳ ngôn ngữ nào khác.
Nó cũng có nghĩa là những người mới bắt đầu với C# có thể bắt đầu với một file C# sạch, và không cần gì khác. Ở giai đoạn sau, họ có thể đi sâu vào các file .csproj.
Cảm ơn bạn đã đọc,
Thomas



