A mustache renderer for .NET built with performance and style in mind.
اشتراکها
A mustache renderer for .NET built with performance and style in mind.
Earlier this week, Microsoft published the roadmap for .NET Core 2.1, ASP.NET Core 2.1 and EF Core 2.1, expected to be out in the first quarter of 2018. The team also talked about several new features with this new release. This release is more of a feedback-oriented release based on .NET Core 2.0 release. The.NET Core 2.0 is a huge success and already more than half a million developers are now using .NET Core 2.0. All thanks to .NET Standard 2.0 release . In this post find out about the new features of .NET Core 2.1.
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <LangVersion>8.0</LangVersion> <NullableContextOptions>enable</NullableContextOptions> </PropertyGroup> </Project>
CS8632: The annotation for nullable reference types should only be used in code within a ‘#nullable’ context. CS8627: A nullable type parameter must be known to be a value-type or non-nullable reference type. Consider adding a ‘class’, ‘struct’ or type constraint.
<PropertyGroup> <LangVersion>preview</LangVersion> <Nullable>enable</Nullable> </PropertyGroup>
public class Person { public string FirstName { get; set; } public string MiddleName { get; set; } public string LastName { get; set; } public Person(string first, string last) => (FirstName, LastName) = (first, last); public Person(string first, string middle, string last) => (FirstName, MiddleName, LastName) = (first, middle, last); public override string ToString() => $"{FirstName} {MiddleName} {LastName}"; }
public string? MiddleName { get; set; }
public static class NullableReferenceTypes { //#nullable enable // Toggle to enable public static string Exemplify() { var vahid = new Person("Vahid", "N"); var length = GetLengthOfMiddleName(vahid); return $"{vahid.FirstName}'s middle name has {length} characters in it."; static int GetLengthOfMiddleName(Person person) { string middleName = person.MiddleName; return middleName.Length; } } }
var middleName = person.MiddleName;
static int GetLengthOfMiddleName(Person person) { var middleName = person.MiddleName; return middleName?.Length ?? 0; }
public static class NullableReferenceTypes { #nullable disable // Toggle to enable
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <LangVersion>8.0</LangVersion> <NullableContextOptions>enable</NullableContextOptions> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> </Project>
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
string name = null; // ERROR string? name = null; // OK!
public class Person { public Address? Address { get; set; }; public string Country => Address?.Country; // ERROR! }
public class Person { public Address? Address { get; set; }; public string? Country => Address?.Country; // OK! }
var node = this; // Initialize non-nullable variable while (node != null) { node = null; // ERROR! }
Node? node = this; // Initialize nullable variable while (node != null) { node = null; // OK! }
public class Person { public string Name { get; set; } // ERROR! }
public class Person { public string? Name { get; set; } }
public class Person { public string Name { get; set; } public Person(string name) { Name = name ?? throw new ArgumentNullException(nameof(name)); } }
public class Person { public string Name { get; set; } = string.Empty; // -or- public string Name { get; set; } = ""; }
String.Empty Array.Empty<T>() Enumerable.Empty<T>()
public class Person { public Address Address { get; set; } = new Address(); }
public enum Rainbow { Red, Orange, Yellow, Green, Blue, Indigo, Violet }
class RGBColor { internal byte Red { get; } internal byte Green { get; } internal byte Blue { get; } internal RGBColor(byte red, byte green, byte blue) { Red = red; Green = green; Blue = blue; } public override string ToString() => $"rgb({Red}, {Green}, {Blue})"; }
internal static RGBColor FromRainbow(Rainbow rainbowBolor) { switch (rainbowBolor) { case Rainbow.Red: return new RGBColor(0xFF, 0x00, 0x00); case Rainbow.Orange: return new RGBColor(0xFF, 0x7F, 0x00); case Rainbow.Yellow: return new RGBColor(0xFF, 0xFF, 0x00); case Rainbow.Green: return new RGBColor(0x00, 0xFF, 0x00); case Rainbow.Blue: return new RGBColor(0x00, 0x00, 0xFF); case Rainbow.Indigo: return new RGBColor(0x4B, 0x00, 0x82); case Rainbow.Violet: return new RGBColor(0x94, 0x00, 0xD3); default: throw new ArgumentException(message: "invalid enum value", paramName: nameof(rainbowBolor)); }; }
internal static RGBColor TasteTheRainbow(Rainbow rainbowColor) => rainbowColor switch { Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00), Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00), Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00), Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00), Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF), Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82), Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3), _ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(rainbowColor)), };
var operation = "+"; int a = 1, b = 2; var result = operation switch { "+" => a + b, "-" => a - b, "/" => a / b, _ => throw new NotSupportedException() };
class Address { public string AddressLine1 { get; set; } public string AddressLine2 { get; set; } public string City { get; set; } public string State { get; set; } public string PostalCode { get; set; } public string CountryRegion { get; set; } }
static class PropertyPatterns { internal static decimal ComputeSalesTax( Address location, decimal salePrice) => location switch { { State: "Fars" } => salePrice * 0.06m, { State: "Tehran", City: "Tehran" } => salePrice * 0.056m, // Other cases removed for brevity... _ => 0M }; }
static class TuplePatterns { internal static string RockPaperScissors( string first, string second) => (first, second) switch { ("rock", "paper") => "Rock is covered by Paper. Paper wins!", ("rock", "scissors") => "Rock breaks Scissors. Rock wins!", ("paper", "rock") => "Paper covers Rock. Paper wins!", ("paper", "scissors") => "Paper is cut by Scissors. Scissors wins!", ("scissors", "rock") => "Scissors is broken by Rock. Rock wins!", ("scissors", "paper") => "Scissors cuts Paper. Scissors wins!", (_, _) => "tie" }; }
class Shape { protected internal double Height { get; } protected internal double Length { get; } protected Shape(double height = 0, double length = 0) { Height = height; Length = length; } } class Circle : Shape { internal double Radius => Height / 2; internal double Diameter => Radius * 2; internal double Circumference => 2 * Math.PI * Radius; internal Circle(double height = 10, double length = 10) : base(height, length) { } } class Rectangle : Shape { internal bool IsSquare => Height == Length; internal Rectangle(double height = 10, double length = 10) : base(height, length) { } }
static class ObjectPatterns { internal static string ShapeDetails(this Shape shape) => shape switch { Circle c => $"circle with (C): {c.Circumference}", Rectangle s when s.IsSquare => $"L:{s.Length} H:{s.Height}, square", Rectangle r => $"L:{r.Length} H:{r.Height}, rectangle", _ => "Unknown shape!" // Discard }; }
class Point { public int X { get; } public int Y { get; } public Point(int x, int y) => (X, Y) = (x, y); public void Deconstruct(out int x, out int y) => (x, y) = (X, Y); } enum Quadrant { Unknown, Origin, One, Two, Three, Four, OnBorder }
static class PositionalPatterns { internal static Quadrant AsQuadrant(Point point) => point switch { (0, 0) => Quadrant.Origin, var (x, y) when x > 0 && y > 0 => Quadrant.One, var (x, y) when x < 0 && y > 0 => Quadrant.Two, var (x, y) when x < 0 && y < 0 => Quadrant.Three, var (x, y) when x > 0 && y < 0 => Quadrant.Four, (_, _) => Quadrant.OnBorder, // Either are 0, but not both _ => Quadrant.Unknown }; }
dotnet new blazor --interactivity Server
dotnet new blazor --interactivity WebAssembly
// ... builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); // ... app.MapRazorComponents<App>() .AddInteractiveServerRenderMode();
// ... builder.Services.AddRazorComponents() .AddInteractiveWebAssemblyComponents(); // ... app.MapRazorComponents<App>() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(Counter).Assembly);
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\BlazorDemoApp.Shared\BlazorDemoApp.Shared.csproj" /> </ItemGroup> </Project>
builder.Services.AddScoped<IProductStore, ProductStore>();
@using static Microsoft.AspNetCore.Components.Web.RenderMode // ... @using BlazorDemoApp.Client.Components.Store @using BlazorDemoApp.Client.Components
<RelatedProducts ProductId="ProductId" @rendermode="@InteractiveWebAssembly"/>
using BlazorDemoApp.Services; using Microsoft.AspNetCore.Mvc; namespace BlazorDemoApp.Controllers; [ApiController] [Route("/api/[controller]")] public class ProductsController : ControllerBase { private readonly IProductStore _store; public ProductsController(IProductStore store) => _store = store; [HttpGet("[action]")] public IActionResult Related([FromQuery] int productId) => Ok(_store.GetRelatedProducts(productId)); }
builder.Services.AddControllers(); // ... app.MapControllers();
@using BlazorDemoApp.Shared.Models @inject HttpClient Http <button class="btn btn-outline-secondary" @onclick="LoadRelatedProducts">Related products</button> @if (_loadRelatedProducts) { @if (_relatedProducts == null) { <p>Loading...</p> } else { <div class="mt-3"> @foreach (var item in _relatedProducts) { <a href="/ProductDetails/@item.Id"> <div class="col-sm"> <h5 class="mt-0">@item.Title (@item.Price.ToString("C"))</h5> </div> </a> } </div> } } @code{ private IList<Product>? _relatedProducts; private bool _loadRelatedProducts; [Parameter] public int ProductId { get; set; } private async Task LoadRelatedProducts() { _loadRelatedProducts = true; var uri = $"/api/products/related?productId={ProductId}"; _relatedProducts = await Http.GetFromJsonAsync<IList<Product>>(uri); } }
System.InvalidOperationException: Cannot provide a value for property 'Http' on type 'RelatedProducts'. There is no registered service of type 'System.Net.Http.HttpClient'.
<RelatedProducts ProductId="ProductId" @rendermode="@InteractiveWebAssembly"/>
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://localhost/") });
using BlazorDemoApp.Shared.Models; namespace BlazorDemoApp.Shared.Data; public interface IProductStore { IList<Product> GetAllProducts(); Product GetProduct(int id); Task<IList<Product>?> GetRelatedProducts(int productId); }
public Task<IList<Product>?> GetRelatedProducts(int productId) { var product = ProductsDataSource.Single(x => x.Id == productId); return Task.FromResult<IList<Product>?>(ProductsDataSource.Where(p => product.Related.Contains(p.Id)) .ToList()); }
[HttpGet("[action]")] public async Task<IActionResult> Related([FromQuery] int productId) => Ok(await _store.GetRelatedProducts(productId));
public class ClientProductStore : IProductStore { private readonly HttpClient _httpClient; public ClientProductStore(HttpClient httpClient) => _httpClient = httpClient; public IList<Product> GetAllProducts() => throw new NotImplementedException(); public Product GetProduct(int id) => throw new NotImplementedException(); public Task<IList<Product>?> GetRelatedProducts(int productId) => _httpClient.GetFromJsonAsync<IList<Product>>($"/api/products/related?productId={productId}"); }
builder.Services.AddScoped<IProductStore, ClientProductStore>(); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
@inject IProductStore ProductStore
private async Task LoadRelatedProducts() { _loadRelatedProducts = true; _relatedProducts = await ProductStore.GetRelatedProducts(ProductId); }