[ADCES] Presentation .NET 8
You can find the presentation about .NET 8 at https://ignatandrei.github.io/Presentations/Net8WhatsNewprez.html#1 . Also, the code is at https://ignatandrei.github.io/Presentations/Net8WhatsNew.zip
You can find the presentation about .NET 8 at https://ignatandrei.github.io/Presentations/Net8WhatsNewprez.html#1 . Also, the code is at https://ignatandrei.github.io/Presentations/Net8WhatsNew.zip
Assumptions:
You have an Blazor Interactive WebAssembly ( CSR ) , not a Server ( static or interactive)
I will make as the repo is https://github.com/ignatandrei/tilt . Change my name with yours and TILT with your repo
So let’s start
Step 1 You must configure GitHub Pages – create a docs folder and put an index.html . Then goto github Settings => Pages (https://github.com/ignatandrei/tilt/settings/pages ) and put there main / docs .
Step 2 Verify it is working. If your repo is https://github.com/ignatandrei/tilt , then browse to https://ignatandrei.github.io/TILT/ and ensure that you can see the index. If not, goto Step 1
Step 3 Add 2 files .nojekyll (content : null , empty …. just create it ) and .gitattributes ( content : *.js binary )
Step 4 dotnet publish your Blazor WASM csproj . Find the folder wwwroot where was published.
Step 5 Find index.html in the folder . Edit base href , put the repo name (<base href=”/TILT/” /> ). Also you can modify the css/js by adding the date ( e.g. <link rel=”stylesheet” href=”css/app.css?202312162300″ /> ) .
Step 6 Copy the index.html and the other files inside the docs folder . Also, copy the index.html as 404.html file
Step 7 Commit and push. Now you can enjoy your Blazor site hosted for free in github : https://github.com/ignatandrei/tilt
Note 1 : If some url’s do not work , then try to add the following
@inject IWebAssemblyHostEnvironment HostEnvironment
@{
var baseAddress = HostEnvironment.BaseAddress;
if (!baseAddress.EndsWith(“/”)) baseAddress += “/”;}
to the url
Note 2: For more deployments please read https://learn.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-8.0
RSCG – InterceptorTemplate
name | InterceptorTemplate |
nuget | https://www.nuget.org/packages/RSCG_InterceptorTemplate/ |
link | https://github.com/ignatandrei/RSCG_InterceptorTemplate |
author | Andrei Ignat |
Andrei Ignat
This is how you can use InterceptorTemplate .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <AdditionalFiles Include="Interceptors\TestFullNameWithArguments.txt"> <CopyToOutputDirectory>Never</CopyToOutputDirectory> </AdditionalFiles> <AdditionalFiles Include="Interceptors\GenericInterceptorForAllMethods.txt"> <CopyToOutputDirectory>Never</CopyToOutputDirectory> </AdditionalFiles> <AdditionalFiles Include="Interceptors\FullName.txt"> <CopyToOutputDirectory>Never</CopyToOutputDirectory> </AdditionalFiles> </ItemGroup> <ItemGroup> <PackageReference Include="RSCG_InterceptorTemplate" Version="8.2023.2811.446" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\RSCG_DemoObjects\RSCG_DemoObjects.csproj" /> </ItemGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);RSCG_InterceptorTemplate</InterceptorsPreviewNamespaces> </PropertyGroup> <PropertyGroup> <TreatWarningsAsErrors>True</TreatWarningsAsErrors> </PropertyGroup> </Project>
The code that you will use is
Console.WriteLine("Run the compile.ps1 file!"); var p=new Person(); p.FirstName="Andrei"; p.LastName="Ignat"; Console.WriteLine("debug for "+p.FullName()); Console.WriteLine("this is "+p.FullName()); var x = p.Test(); Console.WriteLine(x); var newPerson = new Person(); newPerson.FirstName = "Andrei"; newPerson.LastName = "Ignat"; var namePerson = newPerson.FullName(); Console.WriteLine(namePerson); Console.WriteLine("loaded "+Person.PersonsLoaded()); Console.WriteLine("loaded " + RSCG_DemoObjects.Person.PersonsLoaded()); Console.WriteLine("and again " + RSCG_DemoObjects.Person.PersonsLoaded()); Console.WriteLine("and now with argument " + newPerson.TestFullNameWithArguments("<","!+",">",2)); Console.WriteLine("and a random person " + Person.ShowRandomPersonNumber(1)); var q= await PersonLoader.SavePerson(newPerson); PersonLoader.Connect(); //Console.ReadLine(); IPersonLoader ipl=new PersonLoader(); await ipl.InsertPerson(newPerson);
//example generating for full name {{Version}} #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { {{ for loc in ser.dataForEachIntercepts }} //replace code:{{loc.code}}"; //replace code:{{loc.CodeNumbered}}"; [System.Runtime.CompilerServices.InterceptsLocation(@"{{loc.Path}}", {{loc.Line}}, {{loc.StartMethod}})] {{ end }} //[System.Diagnostics.DebuggerStepThrough()] public static {{(ser.item.HasTaskReturnType?"async":"")}} {{ser.item.TypeReturn}} {{ser.item.MethodSignature}}({{ser.item.ThisArgument}} {{ser.item.ArgumentsForCallMethod}} ) { var cc=Console.BackgroundColor ; try{ Console.BackgroundColor = ConsoleColor.DarkGreen; Console.WriteLine("start specific FullName template-->{{ser.item.MethodSignature}}"); {{ser.item.ReturnString}} {{(ser.item.HasTaskReturnType ? "await" : "")}} {{ser.item.CallMethod}}; } finally{ Console.WriteLine("end specific template-->{{ser.item.MethodSignature}}"); Console.BackgroundColor = cc; } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating generic for all methods in a class {{Version}} #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { {{ for loc in ser.dataForEachIntercepts }} //replace code:{{loc.code}}"; //replace code:{{loc.CodeNumbered}}"; [System.Runtime.CompilerServices.InterceptsLocation(@"{{loc.Path}}", {{loc.Line}}, {{loc.StartMethod}})] {{ end }} //[System.Diagnostics.DebuggerStepThrough()] public static {{(ser.item.HasTaskReturnType?"async":"")}} {{ser.item.TypeReturn}} {{ser.item.MethodSignature}}({{ser.item.ThisArgument}} {{ser.item.ArgumentsForCallMethod}} ) { try{ Console.WriteLine("start from generic template-->{{ser.item.MethodSignature}}"); {{ser.item.ReturnString}} {{(ser.item.HasTaskReturnType ? "await" : "")}} {{ser.item.CallMethod}}; } finally{ Console.WriteLine("end from generic template-->{{ser.item.MethodSignature}}"); } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating for full name {{Version}} #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { {{ for loc in ser.dataForEachIntercepts }} //replace code:{{loc.code}}"; //replace code:{{loc.CodeNumbered}}"; [System.Runtime.CompilerServices.InterceptsLocation(@"{{loc.Path}}", {{loc.Line}}, {{loc.StartMethod}})] {{ end }} //[System.Diagnostics.DebuggerStepThrough()] public static {{(ser.item.HasTaskReturnType?"async":"")}} {{ser.item.TypeReturn}} {{ser.item.MethodSignature}}({{ser.item.ThisArgument}} {{ser.item.ArgumentsForCallMethod}} ) { var cc=Console.BackgroundColor ; try{ Console.BackgroundColor = ConsoleColor.DarkGreen; Console.WriteLine("start specific FullName template-->{{ser.item.MethodSignature}}"); {{ser.item.ReturnString}} {{(ser.item.HasTaskReturnType ? "await" : "")}} {{ser.item.CallMethod}}; } finally{ Console.WriteLine("end specific template-->{{ser.item.MethodSignature}}"); Console.BackgroundColor = cc; } } }//end class }//namespace RSCG_InterceptorTemplate
The code that is generated is
//example generating generic for all methods in a class 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:await ipl.InsertPerson(newPerson);"; //replace code:123456789!123456789!123456789!1234"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 25, 11)] //[System.Diagnostics.DebuggerStepThrough()] public static async System.Threading.Tasks.Task<RSCG_DemoObjects.Person> Intercept_ipl_InsertPerson(this RSCG_DemoObjects.IPersonLoader ipl ,RSCG_DemoObjects.Person p ) { try{ Console.WriteLine("start from generic template-->Intercept_ipl_InsertPerson"); return await ipl.InsertPerson(p); } finally{ Console.WriteLine("end from generic template-->Intercept_ipl_InsertPerson"); } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating generic for all methods in a class 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:PersonLoader.Connect();"; //replace code:123456789!123456789!123"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 22, 14)] //[System.Diagnostics.DebuggerStepThrough()] public static void Intercept_PersonLoader_Connect( ) { try{ Console.WriteLine("start from generic template-->Intercept_PersonLoader_Connect"); RSCG_DemoObjects.PersonLoader.Connect(); } finally{ Console.WriteLine("end from generic template-->Intercept_PersonLoader_Connect"); } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating generic for all methods in a class 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:var q= await PersonLoader.SavePerson(newPerson);"; //replace code:123456789!123456789!123456789!123456789!12345678"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 21, 27)] //[System.Diagnostics.DebuggerStepThrough()] public static async System.Threading.Tasks.Task<RSCG_DemoObjects.Person> Intercept_PersonLoader_SavePerson( RSCG_DemoObjects.Person p ) { try{ Console.WriteLine("start from generic template-->Intercept_PersonLoader_SavePerson"); return await RSCG_DemoObjects.PersonLoader.SavePerson(p); } finally{ Console.WriteLine("end from generic template-->Intercept_PersonLoader_SavePerson"); } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating for full name 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:Console.WriteLine("debug for "+p.FullName());"; //replace code:123456789!123456789!123456789!123456789!12345"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 5, 34)] //replace code:Console.WriteLine("this is "+p.FullName());"; //replace code:123456789!123456789!123456789!123456789!123"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 6, 32)] //[System.Diagnostics.DebuggerStepThrough()] public static string Intercept_p_FullName(this RSCG_DemoObjects.Person p ) { var cc=Console.BackgroundColor ; try{ Console.BackgroundColor = ConsoleColor.DarkGreen; Console.WriteLine("start specific FullName template-->Intercept_p_FullName"); return p.FullName(); } finally{ Console.WriteLine("end specific template-->Intercept_p_FullName"); Console.BackgroundColor = cc; } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating for full name 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:var namePerson = newPerson.FullName();"; //replace code:123456789!123456789!123456789!12345678"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 12, 28)] //[System.Diagnostics.DebuggerStepThrough()] public static string Intercept_newPerson_FullName(this RSCG_DemoObjects.Person newPerson ) { var cc=Console.BackgroundColor ; try{ Console.BackgroundColor = ConsoleColor.DarkGreen; Console.WriteLine("start specific FullName template-->Intercept_newPerson_FullName"); return newPerson.FullName(); } finally{ Console.WriteLine("end specific template-->Intercept_newPerson_FullName"); Console.BackgroundColor = cc; } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating generic for all methods in a class 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:Console.WriteLine("loaded "+Person.PersonsLoaded());"; //replace code:123456789!123456789!123456789!123456789!123456789!12"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 15, 36)] //[System.Diagnostics.DebuggerStepThrough()] public static int Intercept_Person_PersonsLoaded( ) { try{ Console.WriteLine("start from generic template-->Intercept_Person_PersonsLoaded"); return RSCG_DemoObjects.Person.PersonsLoaded(); } finally{ Console.WriteLine("end from generic template-->Intercept_Person_PersonsLoaded"); } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating generic for all methods in a class 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:Console.WriteLine("loaded " + RSCG_DemoObjects.Person.PersonsLoaded());"; //replace code:123456789!123456789!123456789!123456789!123456789!123456789!123456789!1"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 16, 55)] //replace code:Console.WriteLine("and again " + RSCG_DemoObjects.Person.PersonsLoaded());"; //replace code:123456789!123456789!123456789!123456789!123456789!123456789!123456789!12345"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 17, 59)] //[System.Diagnostics.DebuggerStepThrough()] public static int Intercept_RSCG_DemoObjects_Person_PersonsLoaded( ) { try{ Console.WriteLine("start from generic template-->Intercept_RSCG_DemoObjects_Person_PersonsLoaded"); return RSCG_DemoObjects.Person.PersonsLoaded(); } finally{ Console.WriteLine("end from generic template-->Intercept_RSCG_DemoObjects_Person_PersonsLoaded"); } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating generic for all methods in a class 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:Console.WriteLine("and a random person " + Person.ShowRandomPersonNumber(1));"; //replace code:123456789!123456789!123456789!123456789!123456789!123456789!123456789!1234567"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 20, 51)] //[System.Diagnostics.DebuggerStepThrough()] public static int Intercept_Person_ShowRandomPersonNumber( int min ) { try{ Console.WriteLine("start from generic template-->Intercept_Person_ShowRandomPersonNumber"); return RSCG_DemoObjects.Person.ShowRandomPersonNumber(min); } finally{ Console.WriteLine("end from generic template-->Intercept_Person_ShowRandomPersonNumber"); } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating for TestFullNameWithArguments 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:Console.WriteLine("and now with argument " + newPerson.TestFullNameWithArguments("<","!+",">",2));"; //replace code:123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!123456789!12345678"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 19, 56)] //[System.Diagnostics.DebuggerStepThrough()] public static string Intercept_newPerson_TestFullNameWithArguments(this RSCG_DemoObjects.Person newPerson ,string start,string separator,string end,int repeat ) { var cc=Console.BackgroundColor ; try{ Console.BackgroundColor = ConsoleColor.DarkRed; Console.WriteLine("start specific TestFullNameWithArguments template-->Intercept_newPerson_TestFullNameWithArguments"); Console.WriteLine("number of arguments = 4"); Console.WriteLine("argument 1 type string and value = "+ start); Console.WriteLine("argument 2 type string and value = "+ separator); Console.WriteLine("argument 3 type string and value = "+ end); Console.WriteLine("argument 4 type int and value = "+ repeat); return newPerson.TestFullNameWithArguments(start,separator,end,repeat); } finally{ Console.WriteLine("end specific template-->Intercept_newPerson_TestFullNameWithArguments"); Console.BackgroundColor = cc; } } }//end class }//namespace RSCG_InterceptorTemplate
//example generating generic for all methods in a class 8.2023.2811.446 #pragma warning disable CS1591 #pragma warning disable CS9113 namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)] file class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }//end namespace namespace RSCG_InterceptorTemplate{ static partial class SimpleIntercept { //replace code:var x = p.Test();"; //replace code:123456789!1234567"; [System.Runtime.CompilerServices.InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\InterceptorTemplate\src\RSCG_InterceptorTemplateConsole\Program.cs", 7, 11)] //[System.Diagnostics.DebuggerStepThrough()] public static string Intercept_p_Test(this RSCG_DemoObjects.Person p ) { try{ Console.WriteLine("start from generic template-->Intercept_p_Test"); return p.Test(); } finally{ Console.WriteLine("end from generic template-->Intercept_p_Test"); } } }//end class }//namespace RSCG_InterceptorTemplate
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/InterceptorTemplate
RSCG – Com
name | Com |
nuget | https://www.nuget.org/packages/System.Runtime.InteropServices/ |
link | https://learn.microsoft.com/en-us/dotnet/standard/native-interop/comwrappers-source-generation |
author | Microsoft |
Generating Com Declarations
This is how you can use Com .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <!-- <PackageReference Include="System.Runtime.InteropServices" /> --> </PropertyGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> </Project>
The code that you will use is
using test; IShellExecute shellExecute = new ShellExecuteClass(); // Open a file using the default associated program IntPtr result = shellExecute.ShellExecute( IntPtr.Zero, // HWND (handle to parent window) "open", // Operation to perform "notepad.exe", // File to open (replace with your file or URL) "", // Parameters "", // Working directory 1 // Show command (SW_SHOWNORMAL) ); Console.WriteLine($"ShellExecute Result: {result}");
using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; namespace test; // Import the ShellExecute function from Shell32.dll using ComImport [ComImport] [Guid("00000000-0000-0000-C000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IUnknown { void QueryInterface(ref Guid riid, out IntPtr ppvObject); void AddRef(); void Release(); } //[ComImport] [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf8)] [Guid("000214F9-0000-0000-C000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public partial interface IShellExecute { IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); } // Replace this with your actual ShellExecute COM class public class ShellExecuteClass : IShellExecute { public IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd) { // Implement the ShellExecute functionality return NativeMethods.ShellExecute(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd); } } // NativeMethods class to import necessary functions from Shell32.dll static class NativeMethods { [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr ShellExecute( IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd ); }
The code that is generated is
// <auto-generated /> #pragma warning disable CS0612, CS0618 file unsafe class InterfaceInformation : global::System.Runtime.InteropServices.Marshalling.IIUnknownInterfaceType { public static global::System.Guid Iid { get; } = new(new global::System.ReadOnlySpan<byte>(new byte[] { 249, 20, 2, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 70 })); private static void** _vtable; public static void** ManagedVirtualMethodTable => _vtable != null ? _vtable : (_vtable = InterfaceImplementation.CreateManagedVirtualFunctionTable()); } [global::System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute] file unsafe partial interface InterfaceImplementation : global::test.IShellExecute { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Interop.ComInterfaceGenerator", "8.0.9.3103")] [global::System.Runtime.CompilerServices.SkipLocalsInitAttribute] nint global::test.IShellExecute.ShellExecute(nint hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd) { var(__this, __vtable_native) = ((global::System.Runtime.InteropServices.Marshalling.IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(typeof(global::test.IShellExecute)); byte* __lpOperation_native = default; byte* __lpFile_native = default; byte* __lpParameters_native = default; byte* __lpDirectory_native = default; nint __retVal = default; int __invokeRetVal = default; // Setup - Perform required setup. scoped global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ManagedToUnmanagedIn __lpDirectory_native__marshaller = new(); scoped global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ManagedToUnmanagedIn __lpParameters_native__marshaller = new(); scoped global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ManagedToUnmanagedIn __lpFile_native__marshaller = new(); scoped global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ManagedToUnmanagedIn __lpOperation_native__marshaller = new(); try { // Marshal - Convert managed data to native data. __lpDirectory_native__marshaller.FromManaged(lpDirectory, stackalloc byte[global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ManagedToUnmanagedIn.BufferSize]); __lpParameters_native__marshaller.FromManaged(lpParameters, stackalloc byte[global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ManagedToUnmanagedIn.BufferSize]); __lpFile_native__marshaller.FromManaged(lpFile, stackalloc byte[global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ManagedToUnmanagedIn.BufferSize]); __lpOperation_native__marshaller.FromManaged(lpOperation, stackalloc byte[global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ManagedToUnmanagedIn.BufferSize]); { // PinnedMarshal - Convert managed data to native data that requires the managed data to be pinned. __lpDirectory_native = __lpDirectory_native__marshaller.ToUnmanaged(); __lpParameters_native = __lpParameters_native__marshaller.ToUnmanaged(); __lpFile_native = __lpFile_native__marshaller.ToUnmanaged(); __lpOperation_native = __lpOperation_native__marshaller.ToUnmanaged(); __invokeRetVal = ((delegate* unmanaged[MemberFunction]<void*, nint, byte*, byte*, byte*, byte*, int, nint*, int> )__vtable_native[3])(__this, hwnd, __lpOperation_native, __lpFile_native, __lpParameters_native, __lpDirectory_native, nShowCmd, &__retVal); } // NotifyForSuccessfulInvoke - Keep alive any managed objects that need to stay alive across the call. global::System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(__invokeRetVal); global::System.GC.KeepAlive(this); } finally { // CleanupCallerAllocated - Perform cleanup of caller allocated resources. __lpDirectory_native__marshaller.Free(); __lpParameters_native__marshaller.Free(); __lpFile_native__marshaller.Free(); __lpOperation_native__marshaller.Free(); } return __retVal; } } file unsafe partial interface InterfaceImplementation { [global::System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute(CallConvs = new[] { typeof(global::System.Runtime.CompilerServices.CallConvMemberFunction) })] internal static int ABI_ShellExecute(global::System.Runtime.InteropServices.ComWrappers.ComInterfaceDispatch* __this_native, nint hwnd, byte* __lpOperation_native, byte* __lpFile_native, byte* __lpParameters_native, byte* __lpDirectory_native, int nShowCmd, nint* __invokeRetValUnmanaged__param) { global::test.IShellExecute @this = default; string lpOperation = default; string lpFile = default; string lpParameters = default; string lpDirectory = default; ref nint __invokeRetValUnmanaged = ref *__invokeRetValUnmanaged__param; nint __invokeRetVal = default; int __retVal = default; try { // Unmarshal - Convert native data to managed data. lpDirectory = global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ConvertToManaged(__lpDirectory_native); lpParameters = global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ConvertToManaged(__lpParameters_native); lpFile = global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ConvertToManaged(__lpFile_native); lpOperation = global::System.Runtime.InteropServices.Marshalling.Utf8StringMarshaller.ConvertToManaged(__lpOperation_native); @this = global::System.Runtime.InteropServices.ComWrappers.ComInterfaceDispatch.GetInstance<global::test.IShellExecute>(__this_native); __invokeRetVal = @this.ShellExecute(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd); // NotifyForSuccessfulInvoke - Keep alive any managed objects that need to stay alive across the call. __retVal = 0; // S_OK // Marshal - Convert managed data to native data. __invokeRetValUnmanaged = __invokeRetVal; } catch (global::System.Exception __exception) { __retVal = global::System.Runtime.InteropServices.Marshalling.ExceptionAsHResultMarshaller<int>.ConvertToUnmanaged(__exception); } return __retVal; } } file unsafe partial interface InterfaceImplementation { internal static void** CreateManagedVirtualFunctionTable() { void** vtable = (void**)global::System.Runtime.CompilerServices.RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(global::test.IShellExecute), sizeof(void*) * 4); { nint v0, v1, v2; global::System.Runtime.InteropServices.ComWrappers.GetIUnknownImpl(out v0, out v1, out v2); vtable[0] = (void*)v0; vtable[1] = (void*)v1; vtable[2] = (void*)v2; } { vtable[3] = (void*)(delegate* unmanaged[MemberFunction]<global::System.Runtime.InteropServices.ComWrappers.ComInterfaceDispatch*, nint, byte*, byte*, byte*, byte*, int, nint*, int> )&ABI_ShellExecute; } return vtable; } } namespace test { [global::System.Runtime.InteropServices.Marshalling.IUnknownDerivedAttribute<InterfaceInformation, InterfaceImplementation>] public partial interface IShellExecute { } } namespace test { public partial interface IShellExecute { } }
Code and pdf at https://ignatandrei.github.io/RSCG_Examples/v2/docs/Com
RSCG – RDG
Generating replacing for minimal API Map
This is how you can use RDG .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <InvariantGlobalization>true</InvariantGlobalization> </PropertyGroup> <ItemGroup> <!-- <PackageReference Include="Microsoft.Extensions.Http"></PackageReference> --> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> </ItemGroup> <PropertyGroup> <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator> </PropertyGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> </Project>
The code that you will use is
var builder = WebApplication.CreateBuilder(args); // Add services to the container. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; app.MapGet("/weatherforecast", () => { var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast ( DateOnly.FromDateTime(DateTime.Now.AddDays(index)), Random.Shared.Next(-20, 55), summaries[Random.Shared.Next(summaries.Length)] )) .ToArray(); return forecast; }) .WithName("GetWeatherForecast") .WithOpenApi(); app.Run(); internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) { public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); }
The code that is generated is
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ #nullable enable namespace System.Runtime.CompilerServices { [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.0.0")] [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] file sealed class InterceptsLocationAttribute : Attribute { public InterceptsLocationAttribute(string filePath, int line, int column) { } } } namespace Microsoft.AspNetCore.Http.Generated { using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text.Json; using System.Text.Json.Serialization.Metadata; using System.Threading.Tasks; using System.IO; using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Json; using Microsoft.AspNetCore.Http.Metadata; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Options; using MetadataPopulator = System.Func<System.Reflection.MethodInfo, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions?, Microsoft.AspNetCore.Http.RequestDelegateMetadataResult>; using RequestDelegateFactoryFunc = System.Func<System.Delegate, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions, Microsoft.AspNetCore.Http.RequestDelegateMetadataResult?, Microsoft.AspNetCore.Http.RequestDelegateResult>; [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.0.0")] file static class GeneratedRouteBuilderExtensionsCore { private static readonly JsonOptions FallbackJsonOptions = new(); private static readonly string[] GetVerb = new[] { global::Microsoft.AspNetCore.Http.HttpMethods.Get }; [InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\RDG\src\RDGDemo\RDGDemoWebApi\Program.cs", 22, 5)] internal static RouteHandlerBuilder MapGet0( this IEndpointRouteBuilder endpoints, [StringSyntax("Route")] string pattern, Delegate handler) { MetadataPopulator populateMetadata = (methodInfo, options) => { Debug.Assert(options != null, "RequestDelegateFactoryOptions not found."); Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found."); options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.0.0")); options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::WeatherForecast[]), contentTypes: GeneratedMetadataConstants.JsonContentType)); return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() }; }; RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) => { Debug.Assert(options != null, "RequestDelegateFactoryOptions not found."); Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found."); Debug.Assert(options.EndpointBuilder.ApplicationServices != null, "ApplicationServices not found."); Debug.Assert(options.EndpointBuilder.FilterFactories != null, "FilterFactories not found."); var handler = Cast(del, global::WeatherForecast[] () => throw null!); EndpointFilterDelegate? filteredInvocation = null; var serviceProvider = options.ServiceProvider ?? options.EndpointBuilder.ApplicationServices; var jsonOptions = serviceProvider?.GetService<IOptions<JsonOptions>>()?.Value ?? FallbackJsonOptions; var jsonSerializerOptions = jsonOptions.SerializerOptions; jsonSerializerOptions.MakeReadOnly(); var objectJsonTypeInfo = (JsonTypeInfo<object?>)jsonSerializerOptions.GetTypeInfo(typeof(object)); var responseJsonTypeInfo = (JsonTypeInfo<global::WeatherForecast[]?>)jsonSerializerOptions.GetTypeInfo(typeof(global::WeatherForecast[])); if (options.EndpointBuilder.FilterFactories.Count > 0) { filteredInvocation = GeneratedRouteBuilderExtensionsCore.BuildFilterDelegate(ic => { if (ic.HttpContext.Response.StatusCode == 400) { return ValueTask.FromResult<object?>(Results.Empty); } return ValueTask.FromResult<object?>(handler()); }, options.EndpointBuilder, handler.Method); } Task RequestHandler(HttpContext httpContext) { var wasParamCheckFailure = false; if (wasParamCheckFailure) { httpContext.Response.StatusCode = 400; return Task.CompletedTask; } var result = handler(); return GeneratedRouteBuilderExtensionsCore.WriteJsonResponseAsync(httpContext.Response, result, responseJsonTypeInfo); } async Task RequestHandlerFiltered(HttpContext httpContext) { var wasParamCheckFailure = false; if (wasParamCheckFailure) { httpContext.Response.StatusCode = 400; } var result = await filteredInvocation(EndpointFilterInvocationContext.Create(httpContext)); if (result is not null) { await GeneratedRouteBuilderExtensionsCore.ExecuteReturnAsync(result, httpContext, objectJsonTypeInfo); } } RequestDelegate targetDelegate = filteredInvocation is null ? RequestHandler : RequestHandlerFiltered; var metadata = inferredMetadataResult?.EndpointMetadata ?? ReadOnlyCollection<object>.Empty; return new RequestDelegateResult(targetDelegate, metadata); }; return MapCore( endpoints, pattern, handler, GetVerb, populateMetadata, createRequestDelegate); } internal static RouteHandlerBuilder MapCore( this IEndpointRouteBuilder routes, string pattern, Delegate handler, IEnumerable<string>? httpMethods, MetadataPopulator populateMetadata, RequestDelegateFactoryFunc createRequestDelegate) { return RouteHandlerServices.Map(routes, pattern, handler, httpMethods, populateMetadata, createRequestDelegate); } private static T Cast<T>(Delegate d, T _) where T : Delegate { return (T)d; } private static EndpointFilterDelegate BuildFilterDelegate(EndpointFilterDelegate filteredInvocation, EndpointBuilder builder, MethodInfo mi) { var routeHandlerFilters = builder.FilterFactories; var context0 = new EndpointFilterFactoryContext { MethodInfo = mi, ApplicationServices = builder.ApplicationServices, }; var initialFilteredInvocation = filteredInvocation; for (var i = routeHandlerFilters.Count - 1; i >= 0; i--) { var filterFactory = routeHandlerFilters[i]; filteredInvocation = filterFactory(context0, filteredInvocation); } return filteredInvocation; } private static Task ExecuteReturnAsync(object? obj, HttpContext httpContext, JsonTypeInfo<object?> jsonTypeInfo) { if (obj is IResult r) { return r.ExecuteAsync(httpContext); } else if (obj is string s) { return httpContext.Response.WriteAsync(s); } else { return WriteJsonResponseAsync(httpContext.Response, obj, jsonTypeInfo); } } [UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The 'JsonSerializer.IsReflectionEnabledByDefault' feature switch, which is set to false by default for trimmed ASP.NET apps, ensures the JsonSerializer doesn't use Reflection.")] [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "See above.")] private static Task WriteJsonResponseAsync<T>(HttpResponse response, T? value, JsonTypeInfo<T?> jsonTypeInfo) { var runtimeType = value?.GetType(); if (jsonTypeInfo.ShouldUseWith(runtimeType)) { return HttpResponseJsonExtensions.WriteAsJsonAsync(response, value, jsonTypeInfo, default); } return response.WriteAsJsonAsync<object?>(value, jsonTypeInfo.Options); } private static bool HasKnownPolymorphism(this JsonTypeInfo jsonTypeInfo) => jsonTypeInfo.Type.IsSealed || jsonTypeInfo.Type.IsValueType || jsonTypeInfo.PolymorphismOptions is not null; private static bool ShouldUseWith(this JsonTypeInfo jsonTypeInfo, [NotNullWhen(false)] Type? runtimeType) => runtimeType is null || jsonTypeInfo.Type == runtimeType || jsonTypeInfo.HasKnownPolymorphism(); } [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.0.0")] file static class GeneratedMetadataConstants { public static readonly string[] JsonContentType = new [] { "application/json" }; public static readonly string[] PlaintextContentType = new [] { "text/plain" }; public static readonly string[] FormFileContentType = new[] { "multipart/form-data" }; public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" }; } [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.0.0")] file sealed class LogOrThrowExceptionHelper { private readonly ILogger? _rdgLogger; private readonly bool _shouldThrow; public LogOrThrowExceptionHelper(IServiceProvider? serviceProvider, RequestDelegateFactoryOptions? options) { var loggerFactory = serviceProvider?.GetRequiredService<ILoggerFactory>(); _rdgLogger = loggerFactory?.CreateLogger("Microsoft.AspNetCore.Http.RequestDelegateGenerator.RequestDelegateGenerator"); _shouldThrow = options?.ThrowOnBadRequest ?? false; } public void RequestBodyIOException(IOException exception) { if (_rdgLogger != null) { _requestBodyIOException(_rdgLogger, exception); } } private static readonly Action<ILogger, Exception?> _requestBodyIOException = LoggerMessage.Define(LogLevel.Debug, new EventId(1, "RequestBodyIOException"), "Reading the request body failed with an IOException."); public void InvalidJsonRequestBody(string parameterTypeName, string parameterName, Exception exception) { if (_shouldThrow) { var message = string.Format(CultureInfo.InvariantCulture, "Failed to read parameter \"{0} {1}\" from the request body as JSON.", parameterTypeName, parameterName); throw new BadHttpRequestException(message, exception); } if (_rdgLogger != null) { _invalidJsonRequestBody(_rdgLogger, parameterTypeName, parameterName, exception); } } private static readonly Action<ILogger, string, string, Exception?> _invalidJsonRequestBody = LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(2, "InvalidJsonRequestBody"), "Failed to read parameter \"{ParameterType} {ParameterName}\" from the request body as JSON."); public void ParameterBindingFailed(string parameterTypeName, string parameterName, string sourceValue) { if (_shouldThrow) { var message = string.Format(CultureInfo.InvariantCulture, "Failed to bind parameter \"{0} {1}\" from \"{2}\".", parameterTypeName, parameterName, sourceValue); throw new BadHttpRequestException(message); } if (_rdgLogger != null) { _parameterBindingFailed(_rdgLogger, parameterTypeName, parameterName, sourceValue, null); } } private static readonly Action<ILogger, string, string, string, Exception?> _parameterBindingFailed = LoggerMessage.Define<string, string, string>(LogLevel.Debug, new EventId(3, "ParameterBindingFailed"), "Failed to bind parameter \"{ParameterType} {ParameterName}\" from \"{SourceValue}\"."); public void RequiredParameterNotProvided(string parameterTypeName, string parameterName, string source) { if (_shouldThrow) { var message = string.Format(CultureInfo.InvariantCulture, "Required parameter \"{0} {1}\" was not provided from {2}.", parameterTypeName, parameterName, source); throw new BadHttpRequestException(message); } if (_rdgLogger != null) { _requiredParameterNotProvided(_rdgLogger, parameterTypeName, parameterName, source, null); } } private static readonly Action<ILogger, string, string, string, Exception?> _requiredParameterNotProvided = LoggerMessage.Define<string, string, string>(LogLevel.Debug, new EventId(4, "RequiredParameterNotProvided"), "Required parameter \"{ParameterType} {ParameterName}\" was not provided from {Source}."); public void ImplicitBodyNotProvided(string parameterName) { if (_shouldThrow) { var message = string.Format(CultureInfo.InvariantCulture, "Implicit body inferred for parameter \"{0}\" but no body was provided. Did you mean to use a Service instead?", parameterName); throw new BadHttpRequestException(message); } if (_rdgLogger != null) { _implicitBodyNotProvided(_rdgLogger, parameterName, null); } } private static readonly Action<ILogger, string, Exception?> _implicitBodyNotProvided = LoggerMessage.Define<string>(LogLevel.Debug, new EventId(5, "ImplicitBodyNotProvided"), "Implicit body inferred for parameter \"{ParameterName}\" but no body was provided. Did you mean to use a Service instead?"); public void UnexpectedJsonContentType(string? contentType) { if (_shouldThrow) { var message = string.Format(CultureInfo.InvariantCulture, "Expected a supported JSON media type but got \"{0}\".", contentType); throw new BadHttpRequestException(message, StatusCodes.Status415UnsupportedMediaType); } if (_rdgLogger != null) { _unexpectedJsonContentType(_rdgLogger, contentType ?? "(none)", null); } } private static readonly Action<ILogger, string, Exception?> _unexpectedJsonContentType = LoggerMessage.Define<string>(LogLevel.Debug, new EventId(6, "UnexpectedContentType"), "Expected a supported JSON media type but got \"{ContentType}\"."); public void UnexpectedNonFormContentType(string? contentType) { if (_shouldThrow) { var message = string.Format(CultureInfo.InvariantCulture, "Expected a supported form media type but got \"{0}\".", contentType); throw new BadHttpRequestException(message, StatusCodes.Status415UnsupportedMediaType); } if (_rdgLogger != null) { _unexpectedNonFormContentType(_rdgLogger, contentType ?? "(none)", null); } } private static readonly Action<ILogger, string, Exception?> _unexpectedNonFormContentType = LoggerMessage.Define<string>(LogLevel.Debug, new EventId(7, "UnexpectedNonFormContentType"), "Expected a supported form media type but got \"{ContentType}\"."); public void InvalidFormRequestBody(string parameterTypeName, string parameterName, Exception exception) { if (_shouldThrow) { var message = string.Format(CultureInfo.InvariantCulture, "Failed to read parameter \"{0} {1}\" from the request body as form.", parameterTypeName, parameterName); throw new BadHttpRequestException(message, exception); } if (_rdgLogger != null) { _invalidFormRequestBody(_rdgLogger, parameterTypeName, parameterName, exception); } } private static readonly Action<ILogger, string, string, Exception?> _invalidFormRequestBody = LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(8, "InvalidFormRequestBody"), "Failed to read parameter \"{ParameterType} {ParameterName}\" from the request body as form."); } }
Code and pdf at https://ignatandrei.github.io/RSCG_Examples/v2/docs/RDG
RSCG – N.SourceGenerators.UnionTypes
name | N.SourceGenerators.UnionTypes |
nuget | https://www.nuget.org/packages/N.SourceGenerators.UnionTypes/ |
link | https://github.com/Ne4to/N.SourceGenerators.UnionTypes |
author | Alexey Sosnin |
Generating different union types
This is how you can use N.SourceGenerators.UnionTypes .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net7.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="N.SourceGenerators.UnionTypes" Version="0.26.0" /> </ItemGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> </Project>
The code that you will use is
using UnionTypesDemo; Console.WriteLine("Save or not"); var data = SaveToDatabase.Save(0); Console.WriteLine(data.IsValidationError); data = SaveToDatabase.Save(1); Console.WriteLine(data.IsSuccess);
using N.SourceGenerators.UnionTypes; namespace UnionTypesDemo; public record Success(int Value); public record ValidationError(string Message); [UnionType(typeof(Success))] [UnionType(typeof(ValidationError))] public partial class ResultSave { }
namespace UnionTypesDemo; public class SaveToDatabase { public static ResultSave Save(int i) { if(i ==0) { return new ValidationError(" cannot save 0"); } return new Success(i); } }
The code that is generated is
// <auto-generated> // This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes // Feel free to open an issue // </auto-generated> #nullable enable using System; using System.Runtime.CompilerServices; namespace N.SourceGenerators.UnionTypes { [AttributeUsage(AttributeTargets.GenericParameter, Inherited = false, AllowMultiple = false)] internal sealed class GenericUnionTypeAttribute : Attribute { public string? Alias { get; set; } public bool AllowNull { get; set; } public object? TypeDiscriminator { get; set; } } }
// <auto-generated> // This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes // Feel free to open an issue // </auto-generated> #nullable enable using System; using System.Runtime.CompilerServices; namespace N.SourceGenerators.UnionTypes { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] internal sealed class JsonPolymorphicUnionAttribute : Attribute { public string? TypeDiscriminatorPropertyName { get; set; } } }
// <auto-generated> // This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes // Feel free to open an issue // </auto-generated> #pragma warning disable #nullable enable namespace UnionTypesDemo { partial class ResultSave : System.IEquatable<ResultSave> { private readonly int _variantId; private const int SuccessId = 1; private readonly global::UnionTypesDemo.Success _success; public bool IsSuccess => _variantId == SuccessId; public global::UnionTypesDemo.Success AsSuccess { get { if (_variantId == SuccessId) return _success; throw new System.InvalidOperationException($"Unable convert to Success. Inner value is {ValueAlias} not Success."); } } public ResultSave(global::UnionTypesDemo.Success success) { System.ArgumentNullException.ThrowIfNull(success); _variantId = SuccessId; _success = success; } public static implicit operator ResultSave(global::UnionTypesDemo.Success success) => new ResultSave(success); public static explicit operator global::UnionTypesDemo.Success(ResultSave value) { if (value._variantId == SuccessId) return value._success; throw new System.InvalidOperationException($"Unable convert to Success. Inner value is {value.ValueAlias} not Success."); } public bool TryGetSuccess([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::UnionTypesDemo.Success value) { if (_variantId == SuccessId) { value = _success; return true; } else { value = default; return false; } } private const int ValidationErrorId = 2; private readonly global::UnionTypesDemo.ValidationError _validationError; public bool IsValidationError => _variantId == ValidationErrorId; public global::UnionTypesDemo.ValidationError AsValidationError { get { if (_variantId == ValidationErrorId) return _validationError; throw new System.InvalidOperationException($"Unable convert to ValidationError. Inner value is {ValueAlias} not ValidationError."); } } public ResultSave(global::UnionTypesDemo.ValidationError validationError) { System.ArgumentNullException.ThrowIfNull(validationError); _variantId = ValidationErrorId; _validationError = validationError; } public static implicit operator ResultSave(global::UnionTypesDemo.ValidationError validationError) => new ResultSave(validationError); public static explicit operator global::UnionTypesDemo.ValidationError(ResultSave value) { if (value._variantId == ValidationErrorId) return value._validationError; throw new System.InvalidOperationException($"Unable convert to ValidationError. Inner value is {value.ValueAlias} not ValidationError."); } public bool TryGetValidationError([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out global::UnionTypesDemo.ValidationError value) { if (_variantId == ValidationErrorId) { value = _validationError; return true; } else { value = default; return false; } } public TOut Match<TOut>(global::System.Func<global::UnionTypesDemo.Success, TOut> matchSuccess, global::System.Func<global::UnionTypesDemo.ValidationError, TOut> matchValidationError) { if (_variantId == SuccessId) return matchSuccess(_success); if (_variantId == ValidationErrorId) return matchValidationError(_validationError); throw new System.InvalidOperationException("Inner type is unknown"); } public async global::System.Threading.Tasks.Task<TOut> MatchAsync<TOut>(global::System.Func<global::UnionTypesDemo.Success, global::System.Threading.CancellationToken, global::System.Threading.Tasks.Task<TOut>> matchSuccess, global::System.Func<global::UnionTypesDemo.ValidationError, global::System.Threading.CancellationToken, global::System.Threading.Tasks.Task<TOut>> matchValidationError, global::System.Threading.CancellationToken ct) { if (_variantId == SuccessId) return await matchSuccess(_success, ct).ConfigureAwait(false); if (_variantId == ValidationErrorId) return await matchValidationError(_validationError, ct).ConfigureAwait(false); throw new System.InvalidOperationException("Inner type is unknown"); } public void Switch(global::System.Action<global::UnionTypesDemo.Success> switchSuccess, global::System.Action<global::UnionTypesDemo.ValidationError> switchValidationError) { if (_variantId == SuccessId) { switchSuccess(_success); return; } if (_variantId == ValidationErrorId) { switchValidationError(_validationError); return; } throw new System.InvalidOperationException("Inner type is unknown"); } public async global::System.Threading.Tasks.Task SwitchAsync(global::System.Func<global::UnionTypesDemo.Success, global::System.Threading.CancellationToken, global::System.Threading.Tasks.Task> switchSuccess, global::System.Func<global::UnionTypesDemo.ValidationError, global::System.Threading.CancellationToken, global::System.Threading.Tasks.Task> switchValidationError, global::System.Threading.CancellationToken ct) { if (_variantId == SuccessId) { await switchSuccess(_success, ct).ConfigureAwait(false); return; } if (_variantId == ValidationErrorId) { await switchValidationError(_validationError, ct).ConfigureAwait(false); return; } throw new System.InvalidOperationException("Inner type is unknown"); } public global::System.Type ValueType { get { if (_variantId == SuccessId) return typeof(global::UnionTypesDemo.Success); if (_variantId == ValidationErrorId) return typeof(global::UnionTypesDemo.ValidationError); throw new System.InvalidOperationException("Inner type is unknown"); } } private string ValueAlias { get { if (_variantId == SuccessId) return "Success"; if (_variantId == ValidationErrorId) return "ValidationError"; throw new System.InvalidOperationException("Inner type is unknown"); } } public override int GetHashCode() { if (_variantId == SuccessId) return _success.GetHashCode(); if (_variantId == ValidationErrorId) return _validationError.GetHashCode(); throw new System.InvalidOperationException("Inner type is unknown"); } public static bool operator ==(ResultSave? left, ResultSave? right) { return Equals(left, right); } public static bool operator !=(ResultSave? left, ResultSave? right) { return !Equals(left, right); } public bool Equals(ResultSave? other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } if (ValueType != other.ValueType) { return false; } if (_variantId == SuccessId) return System.Collections.Generic.EqualityComparer<global::UnionTypesDemo.Success>.Default.Equals(_success, other._success); if (_variantId == ValidationErrorId) return System.Collections.Generic.EqualityComparer<global::UnionTypesDemo.ValidationError>.Default.Equals(_validationError, other._validationError); throw new System.InvalidOperationException("Inner type is unknown"); } public override string ToString() { if (_variantId == SuccessId) return _success.ToString(); if (_variantId == ValidationErrorId) return _validationError.ToString(); throw new System.InvalidOperationException("Inner type is unknown"); } public override bool Equals(object? other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } if (other.GetType() != typeof(ResultSave)) { return false; } return Equals((ResultSave)other); } } }
#nullable enable using System; using System.Runtime.CompilerServices; namespace N.SourceGenerators.UnionTypes { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] sealed class UnionConverterAttribute : Attribute { public Type FromType { get; } public Type ToType { get; } public string? MethodName { get; } public UnionConverterAttribute(Type fromType, Type toType, string? methodName = null) { FromType = fromType; ToType = toType; MethodName = methodName; } } }
// <auto-generated> // This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes // Feel free to open an issue // </auto-generated> #nullable enable using System; using System.Runtime.CompilerServices; namespace N.SourceGenerators.UnionTypes { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] sealed class UnionConverterFromAttribute : Attribute { public Type FromType { get; } public UnionConverterFromAttribute(Type fromType) { FromType = fromType; } } }
// <auto-generated> // This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes // Feel free to open an issue // </auto-generated> #nullable enable using System; using System.Runtime.CompilerServices; namespace N.SourceGenerators.UnionTypes { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] sealed class UnionConverterToAttribute : Attribute { public Type ToType { get; } public UnionConverterToAttribute(Type toType) { ToType = toType; } } }
// <auto-generated> // This code was generated by https://github.com/Ne4to/N.SourceGenerators.UnionTypes // Feel free to open an issue // </auto-generated> #nullable enable using System; using System.Runtime.CompilerServices; namespace N.SourceGenerators.UnionTypes { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] internal sealed class UnionTypeAttribute : Attribute { public Type Type { get; } public string? Alias { get; } public int Order { get; } public bool AllowNull { get; set; } public object? TypeDiscriminator { get; set; } public UnionTypeAttribute(Type type, string? alias = null, [CallerLineNumber] int order = 0) { Type = type; Alias = alias; Order = order; } } }
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/N.SourceGenerators.UnionTypes
RSCG – AutoConstructor
name | AutoConstructor |
nuget | https://www.nuget.org/packages/AutoConstructor/ |
link | https://github.com/k94ll13nn3/AutoConstructor |
author | Kévin Gallienne |
Generating constructor for class with many properties
This is how you can use AutoConstructor .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net7.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="AutoConstructor" Version="4.1.1"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup> </Project>
The code that you will use is
using QuickConstructorDemo; var p = new Person("Andrei", "Ignat"); Console.WriteLine(p.FullName());
namespace QuickConstructorDemo; [AutoConstructor] internal partial class Person { private readonly string FirstName; private readonly string? LastName; public string FullName() => $"{FirstName} {LastName}"; }
The code that is generated is
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by the AutoConstructor source generator. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ [System.AttributeUsage(System.AttributeTargets.Class, Inherited = false, AllowMultiple = false)] internal sealed class AutoConstructorAttribute : System.Attribute { }
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by the AutoConstructor source generator. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ [System.AttributeUsage(System.AttributeTargets.Field, Inherited = false, AllowMultiple = false)] internal sealed class AutoConstructorIgnoreAttribute : System.Attribute { }
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by the AutoConstructor source generator. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ [System.AttributeUsage(System.AttributeTargets.Field, Inherited = false, AllowMultiple = false)] internal sealed class AutoConstructorInjectAttribute : System.Attribute { public AutoConstructorInjectAttribute(string initializer = null, string parameterName = null, System.Type injectedType = null) { Initializer = initializer; ParameterName = parameterName; InjectedType = injectedType; } public string Initializer { get; } public string ParameterName { get; } public System.Type InjectedType { get; } }
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by the AutoConstructor source generator. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ #nullable enable namespace QuickConstructorDemo { partial class Person { public Person(string FirstName, string? LastName) { this.FirstName = FirstName; this.LastName = LastName; } } }
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/AutoConstructor
RSCG – DudNet
name | DudNet |
nuget | https://www.nuget.org/packages/Jwshyns.DudNet/ |
link | https://github.com/jwshyns/DudNet |
author | jwshyns |
Generate proxy classes for the principal classes
This is how you can use DudNet .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net7.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Jwshyns.DudNet" Version="1.2.0" /> </ItemGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> </Project>
The code that you will use is
using DudNetDemo; var p = new Person(); var p1= new PersonProxy(p); p1.FirstName = "John"; p1.LastName = "Doe"; Console.WriteLine(p.FullName()); Console.WriteLine(p1.FullName());
using DudNet.Attributes; using System.Runtime.CompilerServices; namespace DudNetDemo; [ProxyService] public partial class Person : IPerson { public string? FirstName { get; set; } public string? LastName { get; set; } public string FullName() { return FirstName + " " + LastName; } }
The code that is generated is
using System.Runtime.CompilerServices; using DudNet.Attributes; using System.Runtime.CompilerServices; namespace DudNetDemo; /// <inheritdoc cref="IPerson"/> public partial class PersonDud : IPerson { public string? FirstName { get { return (string?) default; } set { } } public string? LastName { get { return (string?) default; } set { } } public string FullName() { return (string) default; } }
using System.Runtime.CompilerServices; using DudNet.Attributes; using System.Runtime.CompilerServices; namespace DudNetDemo; /// <inheritdoc cref="IPerson"/> public partial class PersonProxy : IPerson { private readonly IPerson _service; public string? FirstName { get { Interceptor(); get_FirstNameInterceptor(); return _service.FirstName; } set { Interceptor(); set_FirstNameInterceptor(value); _service.FirstName = value; } } public string? LastName { get { Interceptor(); get_LastNameInterceptor(); return _service.LastName; } set { Interceptor(); set_LastNameInterceptor(value); _service.LastName = value; } } public string FullName() { Interceptor(); FullNameInterceptor(); return _service.FullName(); } partial void Interceptor([CallerMemberName]string callerName = null); partial void get_FirstNameInterceptor(); partial void set_FirstNameInterceptor(string? value); partial void get_LastNameInterceptor(); partial void set_LastNameInterceptor(string? value); partial void FullNameInterceptor(); }
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/DudNet
RSCG – MinimalApiBuilder
name | MinimalApiBuilder |
nuget | https://www.nuget.org/packages/MinimalApiBuilder/ |
link | https://github.com/JensDll/MinimalApiBuilder |
author |
Generate Minimal API from classes
This is how you can use MinimalApiBuilder .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net7.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.12" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> <PackageReference Include="MinimalApiBuilder" Version="1.3.3" /> </ItemGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> </Project>
The code that you will use is
using MinimalApiBuilder; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //MinimalApiBuilder.DependencyInjection.AddMinimalApiBuilderEndpoints(builder.Services); builder.Services.AddMinimalApiBuilderEndpoints(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseAuthorization(); app.MapControllers(); app.MapGet<BasicEndpoint>("/hello"); app.Run();
using Microsoft.AspNetCore.Mvc; using MinimalApiBuilder; public partial class BasicEndpoint : MinimalApiBuilderEndpoint { private static string Handle([FromServices] BasicEndpoint endpoint) { return "Hello, World!"; } }
The code that is generated is
// <auto-generated> // This is a MinimalApiBuilder source generated file. // </auto-generated> #nullable enable namespace MinimalApiBuilder { public static class DependencyInjection { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("MinimalApiBuilder.Generator", "1.3.3.0")] public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddMinimalApiBuilderEndpoints(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services) { global::Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddScoped<global::BasicEndpoint>(services); return services; } } }
// <auto-generated> // This is a MinimalApiBuilder source generated file. // </auto-generated> #nullable enable public partial class BasicEndpoint : global::MinimalApiBuilder.IEndpoint { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("MinimalApiBuilder.Generator", "1.3.3.0")] public static global::System.Delegate _auto_generated_Handler { get; } = Handle; [global::System.CodeDom.Compiler.GeneratedCodeAttribute("MinimalApiBuilder.Generator", "1.3.3.0")] public static void _auto_generated_Configure(global::Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder) { } [global::System.CodeDom.Compiler.GeneratedCodeAttribute("MinimalApiBuilder.Generator", "1.3.3.0")] public static void Configure(global::Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder) { } }
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/MinimalApiBuilder
RSCG – DynamicsMapper
name | DynamicsMapper |
nuget | https://www.nuget.org/packages/YC.DynamicsMapper/ |
link | https://github.com/YonatanCohavi/DynamicsMapper/ |
author | Yonatan Cohavi |
Mapper for Dataverse client – generates also column names from properties
This is how you can use DynamicsMapper .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net7.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.PowerPlatform.Dataverse.Client" Version="1.1.14" /> <PackageReference Include="YC.DynamicsMapper" Version="1.0.8" /> </ItemGroup> </Project>
The code that you will use is
using NextGenMapperDemo; var pm = new PersonMapper(); Console.WriteLine(pm.Entityname);
using DynamicsMapper.Abstractions; namespace NextGenMapperDemo; [CrmEntity("person")] public class Person { [CrmField("personid", Mapping = MappingType.PrimaryId)] public Guid ID { get; set; } [CrmField("name")] public string? Name { get; set; } }
The code that is generated is
// <auto-generated /> #nullable enable using Microsoft.Xrm.Sdk; using System.Linq; namespace DynamicsMapper.Extension { public static class EntityExtension { public static Entity? GetAliasedEntity(this Entity entity, string alias) { var attributes = entity.Attributes.Where(e => e.Key.StartsWith(alias)).ToArray(); if (!attributes.Any()) return null; var aliasEntity = new Entity(); foreach (var attribute in attributes) { if (!(attribute.Value is AliasedValue aliasedValued)) continue; if (string.IsNullOrEmpty(aliasEntity.LogicalName)) aliasEntity.LogicalName = aliasedValued.EntityLogicalName; aliasEntity[aliasedValued.AttributeLogicalName] = aliasedValued.Value; } return aliasEntity; } } }
// <auto-generated /> #nullable enable using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; namespace DynamicsMapper.Mappers { public interface IEntityMapper<T> { public string Entityname { get; } public ColumnSet Columns { get; } public T Map(Entity entity); public T? Map(Entity entity, string alias); public Entity Map(T model); } }
// <auto-generated /> #nullable enable using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using DynamicsMapper.Extension; using DynamicsMapper.Mappers; using System; namespace NextGenMapperDemo { public class PersonMapper : IEntityMapper<Person> { private static readonly string[] columns = new[] { "personid", "name" }; public ColumnSet Columns => new ColumnSet(columns); private const string entityname = "person"; public string Entityname => entityname; public Entity Map(Person person) { var entity = new Entity(entityname); entity.Id = person.ID; entity["name"] = person.Name; return entity; } public Person? Map(Entity entity, string alias) => InternalMap(entity, alias); public Person Map(Entity entity) => InternalMap(entity)!; private static Person? InternalMap(Entity source, string? alias = null) { Entity? entity; if (string.IsNullOrEmpty(alias)) { entity = source; } else { entity = source.GetAliasedEntity(alias); if (entity is null) return null; } if (entity?.LogicalName != entityname) throw new ArgumentException($"entity LogicalName expected to be {entityname} recived: {entity?.LogicalName}", "entity"); var person = new Person(); person.ID = entity.GetAttributeValue<Guid>("personid"); person.Name = entity.GetAttributeValue<string?>("name"); return person; } } }
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/DynamicsMapper