├── .gitattributes ├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── LICENSE ├── README.md ├── ca.ruleset ├── src └── FluentIL │ ├── AssemblyBuilderCache.cs │ ├── AssemblyCache.cs │ ├── Builders │ ├── ArrayBuilder.cs │ ├── FluentAssemblyBuilder.cs │ ├── FluentConstructorBuilder.cs │ ├── FluentDynamicMethodBuilder.cs │ ├── FluentEventBuilder.cs │ ├── FluentFieldBuilder.cs │ ├── FluentGenericParameterBuilder.cs │ ├── FluentMethodBuilder.cs │ ├── FluentModuleBuilder.cs │ ├── FluentParameterBuilder.cs │ ├── FluentPropertyBuilder.cs │ ├── FluentTypeBuilder.cs │ └── MethodInfoBuilder.cs │ ├── ConsoleOutput.cs │ ├── DebugOutput.cs │ ├── DynamicMethodFactory.cs │ ├── Emitters │ ├── DebugEmitter.cs │ ├── DeferredILGeneratorEmitter.cs │ ├── EmitterBase.cs │ ├── ILGeneratorEmitter.cs │ ├── LabelAdapter.cs │ └── LocalAdapter.cs │ ├── Expressions │ ├── ExpressionBuilder.cs │ ├── ExpressionExtensions.cs │ ├── ICondition.cs │ ├── IExpression.cs │ ├── IInitialiser.cs │ └── IIterator.cs │ ├── Extensions │ ├── ConstructorBuilderExtensionMethods.cs │ ├── DynamicMethodExtensionMethods.cs │ ├── EmitterArithmeticExtensions.cs │ ├── EmitterArrayExtensions.cs │ ├── EmitterCompareAndBranchExtensions.cs │ ├── EmitterConvExtensions.cs │ ├── EmitterExtensions.cs │ ├── EmitterLdExtensions.cs │ ├── EmitterLdcExtensions.cs │ ├── EmitterStExtensions.cs │ ├── FieldBuilderExtensionMethods.cs │ ├── MethodBuilderExtensionMethods.cs │ ├── ParameterInfoExtensions.cs │ ├── PropertyExtensionMethods.cs │ ├── ReflectionEmitExtensions.cs │ ├── ReflectionExtensions.cs │ ├── TypeBuilderExtensionMethods.cs │ └── TypeExtensions.cs │ ├── FluentIL.csproj │ ├── FluentIL.sln │ ├── IAdaptedLabel.cs │ ├── IAdaptedLocal.cs │ ├── IAssemblyBuilder.cs │ ├── IConstructorBuilder.cs │ ├── IDebugOutput.cs │ ├── IDynamicMethodBuilder.cs │ ├── IEmitter.cs │ ├── IEventBuilder.cs │ ├── IFieldBuilder.cs │ ├── IGenericParameterBuilder.cs │ ├── ILabel.cs │ ├── ILocal.cs │ ├── IMethodBuilder.cs │ ├── IModuleBuilder.cs │ ├── IParameterBuilder.cs │ ├── IPropertyBuilder.cs │ ├── ITypeBuilder.cs │ ├── TypeFactory.cs │ └── Utility.cs ├── stylecop.json └── test ├── FluentILExamples ├── FluentILExamples.csproj └── Program.cs └── FluentILUnitTests ├── BoxUnBoxUnitTests.cs ├── ConstructorUnitTests.cs ├── DynamicMethodUnitTests.cs ├── EmitForEachUnitTests.cs ├── EmitForUnitTests.cs ├── FluentILUnitTests.csproj ├── ForExpressionUnitTests.cs ├── GenericTypeUnitTests.cs ├── IfExpressionUnitTests.cs ├── ModuleMethodUnitTests.cs ├── ParameterBuilderUnitTests.cs ├── Resources └── ITestInterface.cs ├── TypeFactoryUnitTests.cs ├── TypeInterfaceUnitTests.cs ├── TypeMethodUnitTests.cs └── TypePropertyUnitTests.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | *.md text=auto 7 | 8 | ############################################################################### 9 | # Set default behavior for command prompt diff. 10 | # 11 | # This is need for earlier builds of msysgit that does not have it on by 12 | # default for csharp files. 13 | # Note: This is only used by command line 14 | ############################################################################### 15 | #*.cs diff=csharp 16 | 17 | ############################################################################### 18 | # Set the merge driver for project and solution files 19 | # 20 | # Merging from the command prompt will add diff markers to the files if there 21 | # are conflicts (Merging from VS is not affected by the settings below, in VS 22 | # the diff markers are never inserted). Diff markers may cause the following 23 | # file extensions to fail to load in VS. An alternative would be to treat 24 | # these files as binary and thus will always conflict and require user 25 | # intervention with every merge. To do so, just uncomment the entries below 26 | ############################################################################### 27 | #*.sln merge=binary 28 | #*.csproj merge=binary 29 | #*.vbproj merge=binary 30 | #*.vcxproj merge=binary 31 | #*.vcproj merge=binary 32 | #*.dbproj merge=binary 33 | #*.fsproj merge=binary 34 | #*.lsproj merge=binary 35 | #*.wixproj merge=binary 36 | #*.modelproj merge=binary 37 | #*.sqlproj merge=binary 38 | #*.wwaproj merge=binary 39 | 40 | ############################################################################### 41 | # behavior for image files 42 | # 43 | # image files are treated as binary by default. 44 | ############################################################################### 45 | #*.jpg binary 46 | #*.png binary 47 | #*.gif binary 48 | 49 | ############################################################################### 50 | # diff behavior for common document formats 51 | # 52 | # Convert binary document formats to text before diffing them. This feature 53 | # is only available from the command line. Turn it on by uncommenting the 54 | # entries below. 55 | ############################################################################### 56 | #*.doc diff=astextplain 57 | #*.DOC diff=astextplain 58 | #*.docx diff=astextplain 59 | #*.DOCX diff=astextplain 60 | #*.dot diff=astextplain 61 | #*.DOT diff=astextplain 62 | #*.pdf diff=astextplain 63 | #*.PDF diff=astextplain 64 | #*.rtf diff=astextplain 65 | #*.RTF diff=astextplain -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # Visual Studio code coverage results 114 | *.coverage 115 | *.coveragexml 116 | 117 | # NCrunch 118 | _NCrunch_* 119 | .*crunch*.local.xml 120 | nCrunchTemp_* 121 | 122 | # MightyMoose 123 | *.mm.* 124 | AutoTest.Net/ 125 | 126 | # Web workbench (sass) 127 | .sass-cache/ 128 | 129 | # Installshield output folder 130 | [Ee]xpress/ 131 | 132 | # DocProject is a documentation generator add-in 133 | DocProject/buildhelp/ 134 | DocProject/Help/*.HxT 135 | DocProject/Help/*.HxC 136 | DocProject/Help/*.hhc 137 | DocProject/Help/*.hhk 138 | DocProject/Help/*.hhp 139 | DocProject/Help/Html2 140 | DocProject/Help/html 141 | 142 | # Click-Once directory 143 | publish/ 144 | 145 | # Publish Web Output 146 | *.[Pp]ublish.xml 147 | *.azurePubxml 148 | # TODO: Comment the next line if you want to checkin your web deploy settings 149 | # but database connection strings (with potential passwords) will be unencrypted 150 | *.pubxml 151 | *.publishproj 152 | 153 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 154 | # checkin your Azure Web App publish settings, but sensitive information contained 155 | # in these scripts will be unencrypted 156 | PublishScripts/ 157 | 158 | # NuGet Packages 159 | *.nupkg 160 | # The packages folder can be ignored because of Package Restore 161 | **/packages/* 162 | # except build/, which is used as an MSBuild target. 163 | !**/packages/build/ 164 | # Uncomment if necessary however generally it will be regenerated when needed 165 | #!**/packages/repositories.config 166 | # NuGet v3's project.json files produces more ignoreable files 167 | *.nuget.props 168 | *.nuget.targets 169 | 170 | # Microsoft Azure Build Output 171 | csx/ 172 | *.build.csdef 173 | 174 | # Microsoft Azure Emulator 175 | ecf/ 176 | rcf/ 177 | 178 | # Windows Store app package directories and files 179 | AppPackages/ 180 | BundleArtifacts/ 181 | Package.StoreAssociation.xml 182 | _pkginfo.txt 183 | 184 | # Visual Studio cache files 185 | # files ending in .cache can be ignored 186 | *.[Cc]ache 187 | # but keep track of directories ending in .cache 188 | !*.[Cc]ache/ 189 | 190 | # Others 191 | ClientBin/ 192 | ~$* 193 | *~ 194 | *.dbmdl 195 | *.dbproj.schemaview 196 | *.jfm 197 | *.pfx 198 | *.publishsettings 199 | node_modules/ 200 | orleans.codegen.cs 201 | 202 | # Since there are multiple workflows, uncomment next line to ignore bower_components 203 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 204 | #bower_components/ 205 | 206 | # RIA/Silverlight projects 207 | Generated_Code/ 208 | 209 | # Backup & report files from converting an old project file 210 | # to a newer Visual Studio version. Backup files are not needed, 211 | # because we have git ;-) 212 | _UpgradeReport_Files/ 213 | Backup*/ 214 | UpgradeLog*.XML 215 | UpgradeLog*.htm 216 | 217 | # SQL Server files 218 | *.mdf 219 | *.ldf 220 | 221 | # Business Intelligence projects 222 | *.rdl.data 223 | *.bim.layout 224 | *.bim_*.settings 225 | 226 | # Microsoft Fakes 227 | FakesAssemblies/ 228 | 229 | # GhostDoc plugin setting file 230 | *.GhostDoc.xml 231 | 232 | # Node.js Tools for Visual Studio 233 | .ntvs_analysis.dat 234 | 235 | # Visual Studio 6 build log 236 | *.plg 237 | 238 | # Visual Studio 6 workspace options file 239 | *.opt 240 | 241 | # Visual Studio LightSwitch build output 242 | **/*.HTMLClient/GeneratedArtifacts 243 | **/*.DesktopClient/GeneratedArtifacts 244 | **/*.DesktopClient/ModelManifest.xml 245 | **/*.Server/GeneratedArtifacts 246 | **/*.Server/ModelManifest.xml 247 | _Pvt_Extensions 248 | 249 | # Paket dependency manager 250 | .paket/paket.exe 251 | paket-files/ 252 | 253 | # FAKE - F# Make 254 | .fake/ 255 | 256 | # JetBrains Rider 257 | .idea/ 258 | *.sln.iml 259 | 260 | # CodeRush 261 | .cr/ 262 | 263 | # Python Tools for Visual Studio (PTVS) 264 | __pycache__/ 265 | *.pyc 266 | 267 | # Cake - Uncomment if you are using it 268 | # tools/ 269 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (console)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/test/FluentILExamples/bin/Debug/netcoreapp2.2/FluentILExamples.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/test/FluentILExamples", 16 | // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window 17 | "console": "internalConsole", 18 | "stopAtEntry": false, 19 | "internalConsoleOptions": "openOnSessionStart" 20 | }, 21 | { 22 | "name": ".NET Core Attach", 23 | "type": "coreclr", 24 | "request": "attach", 25 | "processId": "${command:pickProcess}" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "taskName": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/test/FluentILUnitTests/FluentILUnitTests.csproj" 11 | ], 12 | "problemMatcher": "$msCompile" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 P Collyer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FluentIL 2 | 3 | A .NET library for using reflection emit in a fluent way. 4 | 5 | ## Usage 6 | 7 | FluentIL provides fluent syntax for defining types, fields, properties, methods, and events as well as all IL opcodes 8 | to allow types to be created in a much more readable way. 9 | 10 | It also contains syntax for more complex functions like for, foreach, do/while, and if. 11 | 12 | ## Creating Types 13 | 14 | The main way to create a type is using the TypeFactory class. The TypeFactory class contains methods for creating Types, Delegate Types, and Global Methods. 15 | 16 | To create a type you use the NewType() method which returns a ITypeBuilder instance: 17 | 18 | ````c# 19 | var typeBuilder = TypeFactory 20 | .Default 21 | .NewType("TestType"); 22 | ```` 23 | 24 | ## Adding Methods 25 | 26 | Now that you have a type builder you can build your type adding methods, properties, fields, events, etc... 27 | 28 | ````c# 29 | typeBuilder 30 | .NewMethod("Test") 31 | .Public() 32 | .Body() 33 | .LdStr("Hello World") 34 | .Call(typeof(Console).GetMethod("WriteLine")) 35 | .Ret(); 36 | ```` 37 | 38 | Once the type is complete you can turn it into a concrete type using the CreateType() method: 39 | 40 | ````c# 41 | var myType = typeBuilder.CreateType(); 42 | ```` 43 | 44 | Now that you have a concrete type you can begin to use it: 45 | 46 | ````c# 47 | var objInstance = Activator.CreateInstance(myType); 48 | var testAction = objInstance.GetMethodAction("Test"); 49 | testAction(); 50 | ```` 51 | 52 | ## Adding Properties 53 | 54 | ## Conditionals and Expressions 55 | 56 | In addition to the standard IL Op Codes Fluent IL also has high level conditional statements such as If, Else, For, Do, and While. This makes it easier to use by automatically emiting the appropriate IL for those operations. To improve this further contional statements all take expressions. 57 | 58 | ### Example 'If' statement 59 | 60 | ````C# 61 | typeBuilder 62 | .NewMethod("Test") 63 | .Public() 64 | .Param("arg") 65 | .Returns() 66 | .Body(m => m 67 | .DeclareLocal(out ILocal result) 68 | .LdcI4_0() 69 | .StLoc0() 70 | .Nop() 71 | .If(e => e.LdArg0() == 10, 72 | m => m 73 | .LdcI4_1() 74 | .StLoc0()) 75 | .Nop() 76 | .LdLoc(result) 77 | .Ret()); 78 | ```` 79 | 80 | ### Example 'For' statement 81 | 82 | ````C# 83 | typeBuilder 84 | .NewMethod("Test") 85 | .Public() 86 | .Param("arg") 87 | .Body(m => m 88 | .DeclareLocal("localCount", out ILocal localCount) 89 | .DeclareLocal("localItem", out ILocal localItem) 90 | .LdArg1() 91 | .StLoc0() 92 | .Nop() 93 | .For(i => i.LdcI4_0().StLoc(localItem), 94 | c => c.LdLoc(localItem) < c.LdLoc(localCount) && 95 | c.LdLoc(localItem) != 10, 96 | i => i.Inc(localItem), 97 | e => e 98 | .LdStr("Loop {0} of {1}") 99 | .LdLoc1() 100 | .Box() 101 | .LdLoc0() 102 | .Box() 103 | .Call(ConsoleWriteLineStringObjectObject) 104 | .Nop()) 105 | .Ret()); 106 | ```` 107 | 108 | ## Examples 109 | 110 | ### Create Type 111 | 112 | Creates a simple type with no constructors, methods, or properties. 113 | 114 | ````c# 115 | var type = TypeFactory 116 | .Default 117 | .NewType("TestType") 118 | .CreateType(); 119 | ```` 120 | 121 | ### Create Type With Method 122 | 123 | Creates a simple type with a test method that takes a single string parameter and returns it. 124 | 125 | ````c# 126 | var typeBuilder = TypeFactory 127 | .Default 128 | .NewType("TestType"); 129 | 130 | typeBuilder 131 | .NewMethod("TestMethod") 132 | .Public() 133 | .Param("value"); 134 | .Body() 135 | .Declare(out ILocal local) 136 | .LdArg1() 137 | .StLoc(local) 138 | .Nop() 139 | .LdLoc() 140 | .Ret(); 141 | 142 | var type = typeBuilder.CreateType(); 143 | ```` 144 | 145 | ### Create Type with Property 146 | 147 | Creates a simple type with a string property called Value with public get and set methods. 148 | 149 | ````c# 150 | var typeBuilder = TypeFactory 151 | .Default 152 | .NewType("TestType"); 153 | 154 | var fieldValue = typeBuilder 155 | .NewField("value") 156 | .Private(); 157 | 158 | typeBuilder 159 | .NewProperty("Value"); 160 | .Getter(m => m 161 | .Public() 162 | .Body() 163 | .LdArg0() 164 | .LdFld(fieldValue) 165 | .Ret()) 166 | .Setter(m => m 167 | .Public() 168 | .Body() 169 | .LdArg0() 170 | .LdArg1() 171 | .StFld(fieldValue() 172 | .Ret()) 173 | ```` -------------------------------------------------------------------------------- /ca.ruleset: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/FluentIL/AssemblyBuilderCache.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Reflection.Emit; 8 | using FluentIL.Builders; 9 | 10 | /// 11 | /// Represents an cache. 12 | /// 13 | internal class AssemblyBuilderCache 14 | { 15 | /// 16 | /// The cache. 17 | /// 18 | private Dictionary cache; 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public AssemblyBuilderCache() 24 | { 25 | this.cache = new Dictionary(); 26 | } 27 | 28 | /// 29 | /// Gets or creates an and pair. 30 | /// 31 | /// The name of the assembly builder. 32 | /// An assembly builder instance. 33 | public IAssemblyBuilder GetOrCreateAssemblyBuilder(string assemblyName) 34 | { 35 | FluentAssemblyBuilder impl; 36 | if (this.cache.TryGetValue(assemblyName, out impl) == false) 37 | { 38 | AssemblyName name = new AssemblyName(assemblyName); 39 | var builder = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndCollect); 40 | impl = new FluentAssemblyBuilder(builder); 41 | this.cache.Add(assemblyName, impl); 42 | } 43 | 44 | return impl; 45 | } 46 | 47 | /// 48 | /// Removes an assembly builder and all of its module builders. 49 | /// 50 | /// The name of the assembly builder. 51 | /// True if removed; otherwise false. 52 | public bool RemoveAssemblyBuilder(string name) 53 | { 54 | return this.cache.Remove(name); 55 | } 56 | 57 | /// 58 | /// Returns a list of assmiblies. 59 | /// 60 | /// A list of assemblies. 61 | public IEnumerable GetAssemblies() 62 | { 63 | return this.cache.Select(a => a.Value.AssemblyBuilder); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/FluentIL/AssemblyCache.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | #if NETSTANDARD1_6 8 | using Microsoft.DotNet.InternalAbstractions; 9 | using Microsoft.Extensions.DependencyModel; 10 | #endif 11 | 12 | /// 13 | /// Represents a cache of assemblies in the current application. 14 | /// 15 | internal static class AssemblyCache 16 | { 17 | /// 18 | /// Gets a type by name from the cache. 19 | /// 20 | /// The name of the type. 21 | /// Optional value indicating whether only dynamic assemblies should be checked or not. 22 | /// A representing the type if found; otherwise null. 23 | public static Type GetType(string typeName, bool dynamicOnly = false) 24 | { 25 | foreach (var ass in AssemblyCache.GetAssemblies(dynamicOnly)) 26 | { 27 | Type type = ass.GetType(typeName); 28 | if (type != null) 29 | { 30 | return type; 31 | } 32 | } 33 | 34 | return null; 35 | } 36 | 37 | /// 38 | /// Gets a list of loaded assemblies. 39 | /// 40 | /// Optional value indicating whether only dynamic assemblies should be checked or not. 41 | /// A list of assemblies. 42 | public static IEnumerable GetAssemblies(bool dynamicOnly = false) 43 | { 44 | #if NETSTANDARD1_6 45 | var runtimeId = RuntimeEnvironment.GetRuntimeIdentifier(); 46 | var assemblies = 47 | from lib in DependencyContext.Default.GetRuntimeAssemblyNames(runtimeId) 48 | let ass = Assembly.Load(lib) 49 | select ass; 50 | #else 51 | var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 52 | #endif 53 | return FilterAssemblies(assemblies, dynamicOnly); 54 | } 55 | 56 | private static IEnumerable FilterAssemblies(IEnumerable list, bool dynamicOnly) 57 | { 58 | if (list == null) 59 | { 60 | yield break; 61 | } 62 | 63 | foreach (var assembly in list) 64 | { 65 | if (dynamicOnly == false || 66 | assembly.IsDynamic == true) 67 | { 68 | yield return assembly; 69 | } 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/ArrayBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Reflection.Emit; 5 | 6 | /// 7 | /// Generates the IL for handling an array. 8 | /// 9 | public class ArrayBuilder 10 | { 11 | /// 12 | /// The emitter to use. 13 | /// 14 | private readonly IEmitter emitter; 15 | 16 | /// 17 | /// A local varaible to hold the array. 18 | /// 19 | private ILocal localArray; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The . 25 | /// The type of array. 26 | /// The length of the array. 27 | /// Optional local variable. 28 | public ArrayBuilder(IEmitter emitter, Type arrayType, int length, ILocal localArray = null) 29 | { 30 | if (localArray != null && 31 | localArray.LocalType.IsArray == false) 32 | { 33 | throw new InvalidProgramException("The local array type is not an array"); 34 | } 35 | 36 | this.emitter = emitter; 37 | this.localArray = localArray; 38 | if (this.localArray == null) 39 | { 40 | this.emitter.DeclareLocal(arrayType.MakeArrayType(), out this.localArray); 41 | } 42 | 43 | // Create the argument types array. 44 | this.emitter 45 | .LdcI4(length) 46 | .NewArr(arrayType) 47 | .StLoc(this.localArray); 48 | } 49 | 50 | /// 51 | /// Emits the IL to start a set operation for the given index. 52 | /// 53 | /// The array index to set. 54 | public void SetStart(int index) 55 | { 56 | this.emitter 57 | .LdLoc(this.localArray) 58 | .LdcI4(index); 59 | } 60 | 61 | /// 62 | /// Emits the IL to store the element. 63 | /// 64 | public void SetEnd() 65 | { 66 | this.emitter.Emit(OpCodes.Stelem_Ref); 67 | } 68 | 69 | /// 70 | /// Emits the IL to set an element of an array. 71 | /// 72 | /// The index of the element to set. 73 | /// The action to call to emit the set code. 74 | public void Set(int index, Action action) 75 | { 76 | this.SetStart(index); 77 | 78 | if (action != null) 79 | { 80 | action(); 81 | } 82 | 83 | this.SetEnd(); 84 | } 85 | 86 | /// 87 | /// Emits the IL to set an element of an array. 88 | /// 89 | /// The index of the element to set. 90 | /// The action to call to emit the set code. 91 | public void Set(int index, Action action) 92 | { 93 | this.SetStart(index); 94 | 95 | if (action != null) 96 | { 97 | action(index); 98 | } 99 | 100 | this.SetEnd(); 101 | } 102 | 103 | /// 104 | /// Emits the IL to load the given array element onto the evaluation stack. 105 | /// 106 | /// The index of the element to load. 107 | public void Get(int index) 108 | { 109 | this.emitter 110 | .LdLoc(this.localArray) 111 | .LdcI4(index) 112 | .Emit(OpCodes.Ldelem_Ref); 113 | } 114 | 115 | /// 116 | /// Emits the IL to load the array onto the evaluation stack. 117 | /// 118 | public void Load() 119 | { 120 | this.emitter.LdLoc(this.localArray); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentAssemblyBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// An implementation of the interafce. 9 | /// 10 | internal class FluentAssemblyBuilder 11 | : IAssemblyBuilder 12 | { 13 | /// 14 | /// A list of module builders. 15 | /// 16 | private Dictionary modules = new Dictionary(); 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// A instance. 22 | public FluentAssemblyBuilder(AssemblyBuilder assemblyBuilder) 23 | { 24 | this.AssemblyBuilder = assemblyBuilder; 25 | } 26 | 27 | /// 28 | /// Gets an instance. 29 | /// 30 | public AssemblyBuilder AssemblyBuilder { get; } 31 | 32 | /// 33 | /// Defines a module. 34 | /// 35 | /// The name of the module. 36 | /// A instance. 37 | public IModuleBuilder NewDynamicModule(string moduleName) 38 | { 39 | FluentModuleBuilder impl; 40 | if (this.modules.TryGetValue(moduleName, out impl) == false) 41 | { 42 | var module = this.AssemblyBuilder.DefineDynamicModule(moduleName); 43 | impl = new FluentModuleBuilder(module); 44 | this.modules.Add(moduleName, impl); 45 | } 46 | 47 | return impl; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentConstructorBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Reflection.Emit; 8 | using FluentIL.Emitters; 9 | 10 | /// 11 | /// An implementation of the interface. 12 | /// 13 | internal class FluentConstructorBuilder 14 | : IConstructorBuilder 15 | { 16 | /// 17 | /// A function to define the constructor. 18 | /// 19 | private readonly Func define; 20 | 21 | private readonly Func defineDefault; 22 | 23 | /// 24 | /// The constructors calling conversion. 25 | /// 26 | private CallingConventions callingConvention; 27 | 28 | /// 29 | /// A list of constructor parameters. 30 | /// 31 | private List parameters = new List(); 32 | 33 | /// 34 | /// The constuctor builder. 35 | /// 36 | private ConstructorBuilder ctor; 37 | 38 | /// 39 | /// The method implementation attributes. 40 | /// 41 | private MethodImplAttributes methodImplAttributes; 42 | 43 | /// 44 | /// The body emitter. 45 | /// 46 | private EmitterBase body; 47 | 48 | /// 49 | /// Initializes a new instance of the class. 50 | /// 51 | /// A constructor definition function. 52 | public FluentConstructorBuilder( 53 | Func define) 54 | { 55 | this.define = define; 56 | this.callingConvention = CallingConventions.HasThis; 57 | this.body = new DeferredILGeneratorEmitter(); 58 | } 59 | 60 | /// 61 | /// Initializes a new instance of the class. 62 | /// 63 | /// A default constructor definition function. 64 | public FluentConstructorBuilder( 65 | Func define) 67 | { 68 | this.defineDefault = define; 69 | } 70 | 71 | /// 72 | public MethodAttributes MethodAttributes { get; set; } 73 | 74 | /// 75 | public IEmitter Body() 76 | { 77 | return this.body; 78 | } 79 | 80 | /// 81 | public IConstructorBuilder CallingConvention(CallingConventions callingConvention) 82 | { 83 | this.callingConvention = callingConvention; 84 | return this; 85 | } 86 | 87 | /// 88 | public IConstructorBuilder Param(Type parameterType, string parameterName, ParameterAttributes attrs = ParameterAttributes.None) 89 | { 90 | this.parameters.Add( 91 | new FluentParameterBuilder( 92 | parameterType, 93 | parameterName, 94 | attrs)); 95 | 96 | return this; 97 | } 98 | 99 | /// 100 | public IConstructorBuilder Param(IGenericParameterBuilder genericParameterType, string parameterName, ParameterAttributes attrs = ParameterAttributes.None) 101 | { 102 | this.parameters.Add( 103 | new FluentParameterBuilder( 104 | genericParameterType, 105 | parameterName, 106 | attrs)); 107 | 108 | return this; 109 | } 110 | 111 | /// 112 | public IConstructorBuilder Param(Action action) 113 | { 114 | var builder = new FluentParameterBuilder(); 115 | this.parameters.Add(builder); 116 | action(builder); 117 | return this; 118 | } 119 | 120 | /// 121 | public IConstructorBuilder Params(params Type[] parameterTypes) 122 | { 123 | this.parameters = parameterTypes.Select( 124 | t => new FluentParameterBuilder(t, null, ParameterAttributes.None)) 125 | .ToList(); 126 | return this; 127 | } 128 | 129 | /// 130 | public IConstructorBuilder SetMethodAttributes(MethodAttributes attributes) 131 | { 132 | this.MethodAttributes = attributes; 133 | return this; 134 | } 135 | 136 | /// 137 | public IConstructorBuilder SetImplementationFlags(MethodImplAttributes attributes) 138 | { 139 | this.methodImplAttributes = attributes; 140 | return this; 141 | } 142 | 143 | /// 144 | public ConstructorBuilder Define() 145 | { 146 | if (this.ctor != null) 147 | { 148 | return this.ctor; 149 | } 150 | 151 | if (this.define != null) 152 | { 153 | DebugOutput.WriteLine("======================================="); 154 | DebugOutput.Write($"{this.MethodAttributes.OutputMethodAttributes()}"); 155 | DebugOutput.WriteLine("ctor({0})", string.Join(", ", this.parameters.Select(p => $"{p.ParameterType} {p.ParameterName}"))); 156 | DebugOutput.WriteLine("Calling Convention: {0}", this.callingConvention); 157 | DebugOutput.WriteLine(string.Empty); 158 | 159 | var parms = this.parameters.Select(p => p.ParameterType).ToArray(); 160 | 161 | this.ctor = this.define( 162 | this.MethodAttributes, 163 | this.callingConvention, 164 | parms, 165 | null, 166 | null); 167 | 168 | int i = 0; 169 | foreach (var parm in this.parameters) 170 | { 171 | this.ctor.DefineParameter(++i, parm.Attributes, parm.ParameterName); 172 | } 173 | 174 | this.ctor.SetImplementationFlags(this.methodImplAttributes); 175 | 176 | this.body.EmitIL(this.ctor.GetILGenerator()); 177 | } 178 | else if (this.defineDefault != null) 179 | { 180 | this.ctor = this.defineDefault(this.MethodAttributes); 181 | } 182 | 183 | return this.ctor; 184 | } 185 | } 186 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentDynamicMethodBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Reflection.Emit; 8 | using FluentIL.Emitters; 9 | 10 | /// 11 | /// Implementation of the interface. 12 | /// 13 | internal class FluentDynamicMethodBuilder 14 | : IDynamicMethodBuilder 15 | { 16 | /// 17 | /// The methods name. 18 | /// 19 | private string methodName; 20 | 21 | /// 22 | /// The methods owning type. 23 | /// 24 | private Type methodOwner; 25 | 26 | /// 27 | /// The methods return type. 28 | /// 29 | private Type returnType; 30 | 31 | /// 32 | /// The methods parameters. 33 | /// 34 | private List parms = new List(); 35 | 36 | /// 37 | /// The dynamic method. 38 | /// 39 | private DynamicMethod dynamicMethod; 40 | 41 | /// 42 | /// Initializes a new instance of the class. 43 | /// 44 | /// The name of the method. 45 | /// The methods owning type. 46 | internal FluentDynamicMethodBuilder(string methodName, Type methodOwner) 47 | { 48 | this.methodName = methodName; 49 | this.methodOwner = methodOwner; 50 | this.returnType = typeof(void); 51 | } 52 | 53 | /// 54 | /// Throws an exception if the method has been defined. 55 | /// 56 | private void ThrowIfDefined() 57 | { 58 | if (this.dynamicMethod != null) 59 | { 60 | throw new InvalidOperationException("Method already defined"); 61 | } 62 | } 63 | 64 | /// 65 | public IEmitter Body() 66 | { 67 | this.Define(); 68 | 69 | var il = this.dynamicMethod.GetILGenerator(); 70 | var emitter = new ILGeneratorEmitter(il); 71 | if (DebugOutput.Output == null) 72 | { 73 | return emitter; 74 | } 75 | 76 | return new DebugEmitter(emitter, DebugOutput.Output); 77 | } 78 | 79 | /// 80 | public IDynamicMethodBuilder Body(Action action) 81 | { 82 | action(this.Body()); 83 | return this; 84 | } 85 | 86 | /// 87 | public IDynamicMethodBuilder Returns() 88 | { 89 | return this.Returns(typeof(TReturn)); 90 | } 91 | 92 | /// 93 | public IDynamicMethodBuilder Returns(Type returnType) 94 | { 95 | this.ThrowIfDefined(); 96 | this.returnType = returnType; 97 | return this; 98 | } 99 | 100 | /// 101 | public IDynamicMethodBuilder Param(string parameterName, ParameterAttributes attrs = ParameterAttributes.None) 102 | { 103 | return this.Param(typeof(TParam), parameterName, attrs); 104 | } 105 | 106 | /// 107 | public IDynamicMethodBuilder Param(Type parameterType, string parameterName, ParameterAttributes attrs = ParameterAttributes.None) 108 | { 109 | this.ThrowIfDefined(); 110 | this.parms.Add( 111 | new FluentParameterBuilder( 112 | parameterType, 113 | parameterName, 114 | attrs)); 115 | 116 | return this; 117 | } 118 | 119 | /// 120 | public IDynamicMethodBuilder Param(Action action) 121 | { 122 | this.ThrowIfDefined(); 123 | var builder = new FluentParameterBuilder(); 124 | this.parms.Add(builder); 125 | action(builder); 126 | return this; 127 | } 128 | 129 | /// 130 | public IDynamicMethodBuilder Param(IParameterBuilder parameter) 131 | { 132 | this.ThrowIfDefined(); 133 | this.parms.Add((FluentParameterBuilder)parameter); 134 | return this; 135 | } 136 | 137 | /// 138 | public IDynamicMethodBuilder Params(params Type[] parameterTypes) 139 | { 140 | this.ThrowIfDefined(); 141 | this.parms = parameterTypes.Select( 142 | t => new FluentParameterBuilder(t, null, ParameterAttributes.None)) 143 | .ToList(); 144 | return this; 145 | } 146 | 147 | /// 148 | public IDynamicMethodBuilder Params(params IParameterBuilder[] parameters) 149 | { 150 | this.ThrowIfDefined(); 151 | this.parms = parameters 152 | .Cast() 153 | .ToList(); 154 | return this; 155 | } 156 | 157 | /// 158 | public IParameterBuilder CreateParam(string parameterName, ParameterAttributes attrs = ParameterAttributes.None) 159 | { 160 | return this.CreateParam(typeof(TParam), parameterName, attrs); 161 | } 162 | 163 | /// 164 | public IParameterBuilder CreateParam(Type parameterType, string parameterName, ParameterAttributes attrs = ParameterAttributes.None) 165 | { 166 | this.ThrowIfDefined(); 167 | return new FluentParameterBuilder( 168 | parameterType, 169 | parameterName, 170 | attrs); 171 | } 172 | 173 | /// 174 | /// Defines the method. 175 | /// 176 | /// A instance. 177 | public DynamicMethod Define() 178 | { 179 | if (this.dynamicMethod == null) 180 | { 181 | int parmCount = this.parms.Count; 182 | Type[] parameterTypes = new Type[parmCount]; 183 | for (int i = 0; i < parmCount; i++) 184 | { 185 | parameterTypes[i] = this.parms[i].ParameterType; 186 | } 187 | 188 | this.dynamicMethod = new DynamicMethod(this.methodName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, this.returnType, parameterTypes, this.methodOwner, false); 189 | 190 | /* 191 | int parmIndex = 0; 192 | foreach (var parm in this.parms) 193 | { 194 | var paramBuilder = dynamicMethod 195 | .DefineParameter(++parmIndex, parm.Attributes, parm.ParameterName); 196 | 197 | parm.CustomAttributes.SetCustomAttributes(a => paramBuilder.SetCustomAttribute(a)); 198 | } 199 | */ 200 | } 201 | 202 | return this.dynamicMethod; 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentEventBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// Implementation of the interface. 9 | /// 10 | internal class FluentEventBuilder 11 | : IEventBuilder 12 | { 13 | /// 14 | /// The name of the event. 15 | /// 16 | private readonly string eventName; 17 | 18 | /// 19 | /// The events type. 20 | /// 21 | private readonly Type eventType; 22 | 23 | /// 24 | /// A function to define the event. 25 | /// 26 | private readonly Func define; 27 | 28 | /// 29 | /// Initializes a new instance of the class. 30 | /// 31 | /// The events name. 32 | /// The events type. 33 | /// A function to define the event. 34 | public FluentEventBuilder( 35 | string eventName, 36 | Type eventType, 37 | Func define) 38 | { 39 | this.eventName = eventName; 40 | this.eventType = eventType; 41 | this.EventAttributes = EventAttributes.None; 42 | this.define = define; 43 | } 44 | 45 | /// 46 | public EventAttributes EventAttributes { get; private set; } 47 | 48 | /// 49 | public IEventBuilder SpecialName() 50 | { 51 | this.EventAttributes |= EventAttributes.SpecialName; 52 | return this; 53 | } 54 | 55 | /// 56 | public IEventBuilder RTSpecialName() 57 | { 58 | this.EventAttributes |= EventAttributes.RTSpecialName; 59 | return this; 60 | } 61 | 62 | /// 63 | public EventBuilder Define() 64 | { 65 | return this.define( 66 | this.eventName, 67 | this.EventAttributes, 68 | this.eventType); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentFieldBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// Implementation of the interface. 9 | /// 10 | internal class FluentFieldBuilder 11 | : IFieldBuilder 12 | { 13 | /// 14 | /// The function used to define the field. 15 | /// 16 | private readonly Func defineFunc; 17 | 18 | /// 19 | /// The field builder. 20 | /// 21 | private FieldBuilder fieldBuilder; 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// The field name. 27 | /// The field type. 28 | /// The field define function. 29 | public FluentFieldBuilder( 30 | string fieldName, 31 | Type fieldType, 32 | Func defineFunc) 33 | { 34 | this.FieldName = fieldName; 35 | this.FieldType = fieldType; 36 | this.defineFunc = defineFunc; 37 | this.FieldAttributes = FieldAttributes.Private; 38 | } 39 | 40 | /// 41 | public string FieldName { get; } 42 | 43 | /// 44 | public Type FieldType { get; } 45 | 46 | /// 47 | public FieldAttributes FieldAttributes { get; set; } 48 | 49 | /// 50 | public IFieldBuilder Attributes(FieldAttributes attributes) 51 | { 52 | this.FieldAttributes = attributes; 53 | return this; 54 | } 55 | 56 | /// 57 | public FieldBuilder Define() 58 | { 59 | if (this.fieldBuilder == null) 60 | { 61 | this.fieldBuilder = this.defineFunc( 62 | this.FieldName, 63 | this.FieldType, 64 | null, 65 | null, 66 | this.FieldAttributes); 67 | 68 | DebugOutput.WriteLine("======================================="); 69 | DebugOutput.WriteLine("New Field '{0}' [{1}]", this.FieldName, this.FieldType); 70 | DebugOutput.WriteLine("Field Attributes: {0}", this.FieldAttributes); 71 | DebugOutput.WriteLine(string.Empty); 72 | } 73 | 74 | return this.fieldBuilder; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentGenericParameterBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using System.Reflection.Emit; 7 | 8 | /// 9 | /// Implementation of the interface. 10 | /// 11 | internal class FluentGenericParameterBuilder 12 | : IGenericParameterBuilder 13 | { 14 | private readonly Func define; 15 | 16 | private Type baseType; 17 | 18 | private List interfaceTypes; 19 | 20 | private GenericTypeParameterBuilder builder; 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The paramter name. 26 | /// The builder action. 27 | public FluentGenericParameterBuilder( 28 | string parameterName, 29 | Func defineFunc = null) 30 | { 31 | this.ParameterName = parameterName; 32 | this.define = defineFunc; 33 | } 34 | 35 | /// 36 | /// Gets the parameter name. 37 | /// 38 | public string ParameterName { get; } 39 | 40 | /// 41 | /// Gets the parameter builder. 42 | /// 43 | internal GenericTypeParameterBuilder ParameterBuilder => this.builder; 44 | 45 | /// 46 | public GenericParameterAttributes Attributes { get; set; } 47 | 48 | /// 49 | public IGenericParameterBuilder BaseType() 50 | { 51 | return this.BaseType(typeof(T)); 52 | } 53 | 54 | /// 55 | public IGenericParameterBuilder BaseType(Type baseType) 56 | { 57 | this.baseType = baseType; 58 | return this; 59 | } 60 | 61 | /// 62 | public IGenericParameterBuilder InterfaceType() 63 | { 64 | return this.InterfaceType(typeof(T)); 65 | } 66 | 67 | /// 68 | public IGenericParameterBuilder InterfaceType(Type interfaceType) 69 | { 70 | #if NETSTANDARD1_6 71 | if (interfaceType.GetTypeInfo().IsInterface == false) 72 | #else 73 | if (interfaceType.IsInterface == false) 74 | #endif 75 | { 76 | throw new InvalidOperationException("Type must be an interface"); 77 | } 78 | 79 | this.interfaceTypes = this.interfaceTypes ?? new List(); 80 | this.interfaceTypes.Add(interfaceType); 81 | return this; 82 | } 83 | 84 | /// 85 | public IGenericParameterBuilder Contravariant() 86 | { 87 | this.Attributes |= GenericParameterAttributes.Contravariant; 88 | return this; 89 | } 90 | 91 | /// 92 | public IGenericParameterBuilder Covariant() 93 | { 94 | this.Attributes |= GenericParameterAttributes.Covariant; 95 | return this; 96 | } 97 | 98 | /// 99 | public IGenericParameterBuilder DefaultConstructor() 100 | { 101 | this.Attributes |= GenericParameterAttributes.DefaultConstructorConstraint; 102 | return this; 103 | } 104 | 105 | /// 106 | public IGenericParameterBuilder NotNullableValueType() 107 | { 108 | this.Attributes |= GenericParameterAttributes.NotNullableValueTypeConstraint; 109 | return this; 110 | } 111 | 112 | /// 113 | public IGenericParameterBuilder ReferenceType() 114 | { 115 | this.Attributes |= GenericParameterAttributes.ReferenceTypeConstraint; 116 | return this; 117 | } 118 | 119 | public void Build(GenericTypeParameterBuilder builder) 120 | { 121 | this.builder = builder; 122 | 123 | if (this.baseType != null) 124 | { 125 | this.builder.SetBaseTypeConstraint(this.baseType); 126 | } 127 | 128 | if (this.interfaceTypes != null) 129 | { 130 | this.builder.SetInterfaceConstraints(this.interfaceTypes.ToArray()); 131 | } 132 | 133 | this.builder.SetGenericParameterAttributes(this.Attributes); 134 | } 135 | 136 | public Type AsType() 137 | { 138 | #if NETSTANDARD1_6 139 | return this.builder.AsType(); 140 | #else 141 | return this.builder; 142 | #endif 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentModuleBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// Implementation of a . 9 | /// 10 | internal class FluentModuleBuilder 11 | : IModuleBuilder 12 | { 13 | /// 14 | /// A instance. 15 | /// 16 | private readonly ModuleBuilder moduleBuilder; 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// A module builder. 22 | public FluentModuleBuilder(ModuleBuilder moduleBuilder) 23 | { 24 | this.moduleBuilder = moduleBuilder; 25 | } 26 | 27 | /// > 28 | public ITypeBuilder NewType(string typeName) 29 | { 30 | return new FluentTypeBuilder(this.moduleBuilder, typeName); 31 | } 32 | 33 | /// > 34 | public IMethodBuilder NewGlobalMethod(string methodName) 35 | { 36 | return new FluentMethodBuilder( 37 | methodName, 38 | this.moduleBuilder.DefineGlobalMethod, 39 | () => 40 | { 41 | this.CreateGlobalFunctions(); 42 | return this.GetMethod(methodName); 43 | }) 44 | .CallingConvention(CallingConventions.Standard); 45 | } 46 | 47 | /// 48 | public IModuleBuilder CreateGlobalFunctions() 49 | { 50 | this.moduleBuilder.CreateGlobalFunctions(); 51 | return this; 52 | } 53 | 54 | /// 55 | public MethodInfo GetMethod(string methodName) 56 | { 57 | #if NETSTANDARD1_6 58 | return this.moduleBuilder.GetType().GetMethod(methodName); 59 | #else 60 | return this.moduleBuilder.GetMethod(methodName); 61 | #endif 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentParameterBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using System.Reflection.Emit; 7 | 8 | /// 9 | /// An implementation of the interface. 10 | /// 11 | internal class FluentParameterBuilder 12 | : IParameterBuilder 13 | { 14 | /// 15 | /// The parameters type. 16 | /// 17 | private Type parameterType; 18 | 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | public FluentParameterBuilder() 23 | { 24 | } 25 | 26 | /// 27 | /// Initializes a new instance of the class. 28 | /// 29 | /// The parameters type. 30 | /// The parameters name. 31 | /// The parameters attributes. 32 | public FluentParameterBuilder(Type parameterType, string parameterName, ParameterAttributes attrs) 33 | { 34 | this.parameterType = parameterType; 35 | this.ParameterName = parameterName; 36 | this.Attributes = attrs; 37 | } 38 | 39 | /// 40 | /// Initializes a new instance of the class. 41 | /// 42 | /// The parameters type. 43 | /// The parameters name. 44 | /// The parameters attributes. 45 | public FluentParameterBuilder(IGenericParameterBuilder parameterType, string parameterName, ParameterAttributes attrs) 46 | { 47 | this.GenericParameterType = parameterType; 48 | this.ParameterName = parameterName; 49 | this.Attributes = attrs; 50 | } 51 | 52 | /// 53 | /// Gets the generic type parameter. 54 | /// 55 | internal IGenericParameterBuilder GenericParameterType { get; } 56 | 57 | /// 58 | /// Gets the parameters type. 59 | /// 60 | internal Type ParameterType 61 | { 62 | get 63 | { 64 | return this.parameterType ?? this.GenericParameterType.AsType(); 65 | } 66 | } 67 | 68 | /// 69 | /// Gets the parameters name. 70 | /// 71 | internal string ParameterName { get; private set; } 72 | 73 | /// 74 | /// Gets the parameters attributes. 75 | /// 76 | internal ParameterAttributes Attributes { get; private set; } = ParameterAttributes.None; 77 | 78 | /// 79 | /// Gets the parameters custom attributes. 80 | /// 81 | internal List CustomAttributes { get; private set; } 82 | 83 | /// 84 | public IParameterBuilder Type() 85 | { 86 | return this.Type(typeof(T)); 87 | } 88 | 89 | /// 90 | public IParameterBuilder Type(Type parameterType) 91 | { 92 | this.parameterType = parameterType; 93 | return this; 94 | } 95 | 96 | /// 97 | public IParameterBuilder Name(string parameterName) 98 | { 99 | this.ParameterName = parameterName; 100 | return this; 101 | } 102 | 103 | /// 104 | public IParameterBuilder HasDefault() 105 | { 106 | this.Attributes |= ParameterAttributes.HasDefault; 107 | return this; 108 | } 109 | 110 | /// 111 | public IParameterBuilder HasFieldMarshal() 112 | { 113 | this.Attributes |= ParameterAttributes.HasFieldMarshal; 114 | return this; 115 | } 116 | 117 | /// 118 | public IParameterBuilder In() 119 | { 120 | this.Attributes |= ParameterAttributes.In; 121 | return this; 122 | } 123 | 124 | /// 125 | public IParameterBuilder Lcid() 126 | { 127 | this.Attributes |= ParameterAttributes.Lcid; 128 | return this; 129 | } 130 | 131 | /// 132 | public IParameterBuilder Optional() 133 | { 134 | this.Attributes |= ParameterAttributes.Optional; 135 | return this; 136 | } 137 | 138 | /// 139 | public IParameterBuilder Out() 140 | { 141 | this.Attributes |= ParameterAttributes.Out; 142 | return this; 143 | } 144 | 145 | /// 146 | public IParameterBuilder Retval() 147 | { 148 | this.Attributes |= ParameterAttributes.Retval; 149 | return this; 150 | } 151 | 152 | /// 153 | public IParameterBuilder SetCustomAttribute(CustomAttributeBuilder attributeBuilder) 154 | { 155 | this.CustomAttributes = this.CustomAttributes ?? new List(); 156 | this.CustomAttributes.Add(attributeBuilder); 157 | return this; 158 | } 159 | } 160 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/FluentPropertyBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using System.Reflection.Emit; 7 | 8 | /// 9 | /// Implementation of the interface. 10 | /// 11 | internal class FluentPropertyBuilder 12 | : IPropertyBuilder 13 | { 14 | /// 15 | /// A function to define a property. 16 | /// 17 | private readonly Func define; 18 | 19 | /// 20 | /// A type builder. 21 | /// 22 | private readonly ITypeBuilder typeBuilder; 23 | 24 | /// 25 | /// The property name. 26 | /// 27 | private readonly string name; 28 | 29 | /// 30 | /// The property type. 31 | /// 32 | private Type propertyType; 33 | 34 | /// 35 | /// The calling convention. 36 | /// 37 | private CallingConventions callingConvention = CallingConventions.HasThis; 38 | 39 | /// 40 | /// The defined property builder. 41 | /// 42 | private PropertyBuilder propertyBuilder; 43 | 44 | /// 45 | /// Initializes a new instance of the class. 46 | /// 47 | /// A instance. 48 | /// The name of the property. 49 | /// The property type. 50 | /// A function to define the property. 51 | public FluentPropertyBuilder( 52 | ITypeBuilder typeBuilder, 53 | string propertyName, 54 | Type propertyType, 55 | Func define) 56 | { 57 | this.define = define; 58 | this.typeBuilder = typeBuilder; 59 | this.name = propertyName; 60 | this.propertyType = propertyType; 61 | this.PropertyAttributes = PropertyAttributes.None; 62 | } 63 | 64 | /// 65 | public PropertyAttributes PropertyAttributes { get; set; } 66 | 67 | /// 68 | public IMethodBuilder SetMethod { get; set; } 69 | 70 | /// 71 | public IMethodBuilder GetMethod { get; set; } 72 | 73 | /// 74 | public IPropertyBuilder Getter(Action action) 75 | { 76 | action.Invoke(this.Getter()); 77 | return this; 78 | } 79 | 80 | /// 81 | public IMethodBuilder Getter() 82 | { 83 | if (this.GetMethod == null) 84 | { 85 | this.GetMethod = this.typeBuilder 86 | .NewMethod($"get_{this.name}") 87 | .CallingConvention(this.callingConvention) 88 | .SpecialName() 89 | .Returns(this.propertyType); 90 | } 91 | 92 | return this.GetMethod; 93 | } 94 | 95 | /// 96 | public IPropertyBuilder Setter(Action action) 97 | { 98 | action.Invoke(this.Setter()); 99 | return this; 100 | } 101 | 102 | /// 103 | public IMethodBuilder Setter() 104 | { 105 | if (this.SetMethod == null) 106 | { 107 | this.SetMethod = this.typeBuilder 108 | .NewMethod($"set_{this.name}") 109 | .CallingConvention(this.callingConvention) 110 | .Param(this.propertyType, "value", ParameterAttributes.None) 111 | .Returns(typeof(void)); 112 | } 113 | 114 | return this.SetMethod; 115 | } 116 | 117 | /// 118 | public IPropertyBuilder Attributes(PropertyAttributes attributes) 119 | { 120 | this.PropertyAttributes = attributes; 121 | return this; 122 | } 123 | 124 | /// 125 | public IPropertyBuilder CallingConvention(CallingConventions callingConvention) 126 | { 127 | this.callingConvention = callingConvention; 128 | return this; 129 | } 130 | 131 | /// 132 | public PropertyBuilder Define() 133 | { 134 | if (this.propertyBuilder == null) 135 | { 136 | this.propertyBuilder = this.define( 137 | this.name, 138 | this.PropertyAttributes, 139 | this.callingConvention, 140 | this.propertyType, 141 | null, 142 | null, 143 | null, 144 | null, 145 | null); 146 | 147 | if (this.GetMethod != null) 148 | { 149 | this.propertyBuilder.SetGetMethod(this.GetMethod.Define()); 150 | } 151 | 152 | if (this.SetMethod != null) 153 | { 154 | this.propertyBuilder.SetSetMethod(this.SetMethod.Define()); 155 | } 156 | 157 | DebugOutput.WriteLine(string.Empty); 158 | DebugOutput.WriteLine("======================================="); 159 | DebugOutput.WriteLine("Property {0} Defined", this.name); 160 | DebugOutput.WriteLine("Calling Convention: {0}", this.callingConvention); 161 | DebugOutput.WriteLine("Attributes: {0}", this.propertyBuilder.Attributes); 162 | DebugOutput.WriteLine(string.Empty); 163 | } 164 | 165 | return this.propertyBuilder; 166 | } 167 | } 168 | } -------------------------------------------------------------------------------- /src/FluentIL/Builders/MethodInfoBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Builders 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | /// 9 | /// Represents a builder. 10 | /// 11 | public class MethodInfoBuilder 12 | { 13 | /// 14 | /// A list of matching methods. 15 | /// 16 | private IEnumerable methods; 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// The type that the method belongs to. 22 | /// The name of the method to find. 23 | public MethodInfoBuilder(Type type, string methodName) 24 | { 25 | this.methods = type 26 | .GetMethods() 27 | .Where(m => m.Name == methodName); 28 | } 29 | 30 | /// 31 | /// Looks forgeneric definition methods. 32 | /// 33 | /// The instance. 34 | public MethodInfoBuilder IsGenericDefinition() 35 | { 36 | this.methods = this.methods.Where(m => m.IsGenericMethodDefinition); 37 | return this; 38 | } 39 | 40 | /// 41 | /// Lokks for methods with matching parameter types. 42 | /// 43 | /// A list of parameter types. 44 | /// The instance. 45 | public MethodInfoBuilder HasParameterTypes(params Type[] types) 46 | { 47 | this.methods = this.methods 48 | .Select(m => new 49 | { 50 | Method = m, 51 | Parms = m.GetParameters() 52 | }) 53 | .Where(m => 54 | m.Parms.Length == types.Length && 55 | this.ParameterTypesMatch(m.Parms, types)) 56 | .Select(m => m.Method); 57 | 58 | return this; 59 | } 60 | 61 | /// 62 | /// Looks for methods with a given metadata token. 63 | /// 64 | /// THe metadata token. 65 | /// The instance. 66 | public MethodInfoBuilder HasMetadataToken(int metadataToken) 67 | { 68 | #if NETSTANDARD1_6 69 | #else 70 | this.methods = this.methods 71 | .Where(m => m.MetadataToken == metadataToken); 72 | #endif 73 | 74 | return this; 75 | } 76 | 77 | /// 78 | /// Returns the first method found or null if there are no matching methods. 79 | /// 80 | /// A instance; otherwise null. 81 | public MethodInfo FirstOrDefault() 82 | { 83 | return this.methods.FirstOrDefault(); 84 | } 85 | 86 | /// 87 | /// Returns all matching methods. 88 | /// 89 | /// A list of matching instances. 90 | public IEnumerable All() 91 | { 92 | return this.methods; 93 | } 94 | 95 | /// 96 | /// Checks if the parameters match the types. 97 | /// 98 | /// The methods parameters. 99 | /// The type list to match with. 100 | /// True or false. 101 | private bool ParameterTypesMatch(ParameterInfo[] parms, Type[] types) 102 | { 103 | if (parms.Length < types.Length) 104 | { 105 | return false; 106 | } 107 | 108 | for (int i = 0; i < types.Length; i++) 109 | { 110 | if (types[i] != null) 111 | { 112 | Type parmType = parms[i].ParameterType; 113 | #if NETSTANDARD1_6 114 | if (types[i].GetTypeInfo().IsGenericTypeDefinition == true) 115 | #else 116 | if (types[i].IsGenericTypeDefinition == true) 117 | #endif 118 | { 119 | parmType = parmType.GetGenericTypeDefinition(); 120 | } 121 | 122 | if (parmType != types[i]) 123 | { 124 | return false; 125 | } 126 | } 127 | } 128 | 129 | return true; 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /src/FluentIL/ConsoleOutput.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | 5 | /// 6 | /// Console implementation of the interface. 7 | /// 8 | public class ConsoleOutput 9 | : IDebugOutput 10 | { 11 | /// 12 | public void Write(string format, params object[] args) 13 | { 14 | Console.Write(format, args); 15 | } 16 | 17 | /// 18 | public void WriteLine(string format, params object[] args) 19 | { 20 | Console.WriteLine(format, args); 21 | } 22 | 23 | /// 24 | public void WriteColor(ConsoleColor color, string format, params object[] args) 25 | { 26 | var oldColor = this.SetConsoleColor(color); 27 | Console.Write(format, args); 28 | this.SetConsoleColor(oldColor); 29 | } 30 | 31 | /// 32 | public void WriteLineColor(ConsoleColor color, string format, params object[] args) 33 | { 34 | var oldColor = this.SetConsoleColor(color); 35 | Console.WriteLine(format, args); 36 | this.SetConsoleColor(oldColor); 37 | } 38 | 39 | private ConsoleColor SetConsoleColor(ConsoleColor color) 40 | { 41 | var oldColor = Console.ForegroundColor; 42 | Console.ForegroundColor = color; 43 | return oldColor; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/FluentIL/DebugOutput.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Text; 6 | 7 | /// 8 | /// Debug output helper. 9 | /// 10 | public static class DebugOutput 11 | { 12 | /// 13 | /// Gets or sets the instance. 14 | /// 15 | /// The instsnce. 16 | public static IDebugOutput Output { get; set; } 17 | 18 | /// 19 | /// Writes to debug output. 20 | /// 21 | /// A string format. 22 | /// The format arguments. 23 | internal static void Write(string format, params object[] args) 24 | { 25 | Output?.Write(format, args); 26 | } 27 | 28 | /// 29 | /// Writes a line to debug output. 30 | /// 31 | /// A string format. 32 | /// The format arguments. 33 | internal static void WriteLine(string format, params object[] args) 34 | { 35 | Output?.WriteLine(format, args); 36 | } 37 | 38 | /// 39 | /// Writes to debug output in a specified colour. 40 | /// 41 | /// The colour of the string. 42 | /// A string format. 43 | /// The format arguments. 44 | internal static void WriteColor(ConsoleColor color, string format, params object[] args) 45 | { 46 | Output?.WriteColor(color, format, args); 47 | } 48 | 49 | /// 50 | /// Writes a line to debug output in a specified colour. 51 | /// 52 | /// The colour of the string. 53 | /// A string format. 54 | /// The format arguments. 55 | internal static void WriteLineColor(ConsoleColor color, string format, params object[] args) 56 | { 57 | Output?.WriteLineColor(color, format, args); 58 | } 59 | 60 | /// 61 | /// Outputs method attributes as a string. 62 | /// 63 | /// The method attributes. 64 | /// A string representation. 65 | internal static string OutputMethodAttributes(this MethodAttributes methodAttributes) 66 | { 67 | var str = new StringBuilder(); 68 | if ((methodAttributes & System.Reflection.MethodAttributes.Private) != 0) 69 | { 70 | str.Append("private "); 71 | } 72 | else if ((methodAttributes & System.Reflection.MethodAttributes.Public) != 0) 73 | { 74 | str.Append("public "); 75 | } 76 | else if ((methodAttributes & System.Reflection.MethodAttributes.Family) != 0) 77 | { 78 | str.Append("protected "); 79 | } 80 | else if ((methodAttributes & System.Reflection.MethodAttributes.Assembly) != 0) 81 | { 82 | str.Append("internal "); 83 | } 84 | else if ((methodAttributes & System.Reflection.MethodAttributes.FamANDAssem) != 0) 85 | { 86 | str.Append("protected internal"); 87 | } 88 | 89 | if ((methodAttributes & System.Reflection.MethodAttributes.Static) != 0) 90 | { 91 | str.Append("static "); 92 | } 93 | 94 | if ((methodAttributes & System.Reflection.MethodAttributes.Virtual) != 0) 95 | { 96 | str.Append("virtual "); 97 | } 98 | 99 | if ((methodAttributes & System.Reflection.MethodAttributes.Final) != 0) 100 | { 101 | str.Append("sealed "); 102 | } 103 | 104 | if ((methodAttributes & System.Reflection.MethodAttributes.Abstract) != 0) 105 | { 106 | str.Append("abstract "); 107 | } 108 | 109 | return str.ToString(); 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /src/FluentIL/DynamicMethodFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using FluentIL.Builders; 5 | 6 | /// 7 | /// Represents a dynamic method factory. 8 | /// 9 | public class DynamicMethodFactory 10 | { 11 | /// 12 | /// The default instance. 13 | /// 14 | private static Lazy instance = new Lazy(() => new DynamicMethodFactory(), true); 15 | 16 | /// 17 | /// Gets the default dynamic method factory. 18 | /// 19 | public static DynamicMethodFactory Default 20 | { 21 | get 22 | { 23 | return instance.Value; 24 | } 25 | } 26 | 27 | /// 28 | /// Creates a new dynamic method. 29 | /// 30 | /// The methods name. 31 | /// The methods owner. 32 | /// A instance. 33 | public IDynamicMethodBuilder NewDynamicMethod(string methodName, Type methodOwner) 34 | { 35 | return new FluentDynamicMethodBuilder(methodName, methodOwner); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/FluentIL/Emitters/LabelAdapter.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Emitters 2 | { 3 | using System; 4 | 5 | /// 6 | /// A label adapter. 7 | /// 8 | internal class LabelAdapter 9 | : ILabel, 10 | IAdaptedLabel 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// The name of the label. 16 | /// The label. 17 | internal LabelAdapter(string name, object label = null) 18 | { 19 | this.Name = name; 20 | this.Label = label; 21 | } 22 | 23 | /// 24 | public object Label { get; set; } 25 | 26 | /// 27 | public string Name { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /src/FluentIL/Emitters/LocalAdapter.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Emitters 2 | { 3 | using System; 4 | 5 | /// 6 | /// A local variable adapter. 7 | /// 8 | internal class LocalAdapter 9 | : ILocal, 10 | IAdaptedLocal 11 | { 12 | private readonly IGenericParameterBuilder genericParameter; 13 | 14 | private readonly IGenericParameterBuilder[] genericTypeArgs; 15 | 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// The name of the local. 20 | internal LocalAdapter(string name) 21 | { 22 | this.Name = name; 23 | } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// 28 | /// The name of the local. 29 | /// The locals type. 30 | /// The locals index. 31 | /// A value indicating wheteher or not the local is pinned. 32 | /// The local instance. 33 | internal LocalAdapter(string name, Type localType, int localIndex, bool isPinned, object local = null) 34 | { 35 | this.Name = name; 36 | this.LocalType = localType; 37 | this.LocalIndex = localIndex; 38 | this.IsPinned = isPinned; 39 | this.Local = local; 40 | } 41 | 42 | /// 43 | /// Initializes a new instance of the class. 44 | /// 45 | /// The name of the local. 46 | /// A generic parameter. 47 | /// The local instance. 48 | internal LocalAdapter(string name, IGenericParameterBuilder genericParameter, object local = null) 49 | { 50 | this.Name = name; 51 | this.genericParameter = genericParameter; 52 | this.Local = local; 53 | } 54 | 55 | /// 56 | /// Initializes a new instance of the class. 57 | /// 58 | /// The name of the local. 59 | /// The local type definition. 60 | /// An array of generic type arguments. 61 | /// The local instance. 62 | internal LocalAdapter(string name, Type localTypeDefinition, IGenericParameterBuilder[] genericTypeArgs, object local = null) 63 | { 64 | this.Name = name; 65 | this.LocalType = localTypeDefinition; 66 | this.genericTypeArgs = genericTypeArgs; 67 | this.Local = local; 68 | } 69 | 70 | /// 71 | public object Local { get; set; } 72 | 73 | /// 74 | public string Name { get; } 75 | 76 | /// 77 | public bool IsPinned { get; } 78 | 79 | /// 80 | public int LocalIndex { get; set; } 81 | 82 | /// 83 | public Type LocalType { get; set; } 84 | } 85 | } -------------------------------------------------------------------------------- /src/FluentIL/Expressions/ExpressionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Expressions 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Reflection; 8 | using System.Runtime.CompilerServices; 9 | using FluentIL; 10 | 11 | /// 12 | /// Expression extension methods. 13 | /// 14 | public static class ExpressionExtensions 15 | { 16 | /// 17 | /// A list of supported method. 18 | /// 19 | private static readonly MethodInfo[] SupportedMethods = new[] 20 | { 21 | typeof(EmitterLdExtensions).GetMethod("LdArg0", new[] { typeof(IEmitter) }), 22 | typeof(EmitterLdExtensions).GetMethod("LdArg1", new[] { typeof(IEmitter) }), 23 | typeof(EmitterLdExtensions).GetMethod("LdArg2", new[] { typeof(IEmitter) }), 24 | typeof(EmitterLdExtensions).GetMethod("LdArg3", new[] { typeof(IEmitter) }), 25 | typeof(EmitterLdExtensions).GetMethod("LdLoc", new[] { typeof(IEmitter), typeof(ILocal) }), 26 | typeof(EmitterLdExtensions).GetMethod("LdLoc0", new[] { typeof(IEmitter) }), 27 | typeof(EmitterLdExtensions).GetMethod("LdLoc1", new[] { typeof(IEmitter) }), 28 | typeof(EmitterLdExtensions).GetMethod("LdLoc2", new[] { typeof(IEmitter) }), 29 | typeof(EmitterLdExtensions).GetMethod("LdLoc3", new[] { typeof(IEmitter) }), 30 | typeof(EmitterStExtensions).GetMethod("StLoc", new[] { typeof(IEmitter), typeof(ILocal) }), 31 | typeof(EmitterStExtensions).GetMethod("StLoc0", new[] { typeof(IEmitter) }), 32 | typeof(EmitterStExtensions).GetMethod("StLoc1", new[] { typeof(IEmitter) }), 33 | typeof(EmitterStExtensions).GetMethod("StLoc2", new[] { typeof(IEmitter) }), 34 | typeof(EmitterStExtensions).GetMethod("StLoc3", new[] { typeof(IEmitter) }), 35 | typeof(EmitterLdExtensions).GetMethod("LdFld", new[] { typeof(IEmitter), typeof(IFieldBuilder) }), 36 | typeof(EmitterStExtensions).GetMethod("StFld", new[] { typeof(IEmitter), typeof(IFieldBuilder) }), 37 | typeof(EmitterLdExtensions).GetMethod("LdNull", new[] { typeof(IEmitter) }), 38 | typeof(EmitterLdcExtensions).GetMethod("LdcI4", new[] { typeof(IEmitter), typeof(int) }), 39 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_0", new[] { typeof(IEmitter) }), 40 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_1", new[] { typeof(IEmitter) }), 41 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_2", new[] { typeof(IEmitter) }), 42 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_3", new[] { typeof(IEmitter) }), 43 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_4", new[] { typeof(IEmitter) }), 44 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_5", new[] { typeof(IEmitter) }), 45 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_6", new[] { typeof(IEmitter) }), 46 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_7", new[] { typeof(IEmitter) }), 47 | typeof(EmitterLdcExtensions).GetMethod("LdcI4_8", new[] { typeof(IEmitter) }), 48 | typeof(EmitterArithmeticExtensions).GetMethod("Add", new[] { typeof(IEmitter) }), 49 | typeof(EmitterArithmeticExtensions).GetMethod("Sub", new[] { typeof(IEmitter) }), 50 | typeof(EmitterExtensions).GetMethod("Inc", new[] { typeof(IEmitter), typeof(ILocal) }), 51 | typeof(EmitterExtensions).GetMethod("Dec", new[] { typeof(IEmitter), typeof(ILocal) }), 52 | typeof(EmitterExtensions).GetMethod("Call", new[] { typeof(IEmitter), typeof(MethodInfo) }), 53 | }; 54 | 55 | /// 56 | /// Emits an expression method. 57 | /// 58 | /// A reference to an emitter. 59 | /// A reference to the expression method. 60 | /// A reference to the argument stack. 61 | internal static void EmitMethod(this IEmitter emitter, MethodInfo expressionMethod, Stack arguments) 62 | { 63 | if (expressionMethod.DeclaringType == typeof(IExpression) || 64 | expressionMethod.DeclaringType == typeof(IInitialiser) || 65 | expressionMethod.DeclaringType == typeof(ICondition) || 66 | expressionMethod.DeclaringType == typeof(IIterator)) 67 | { 68 | if (expressionMethod.Name != "Value") 69 | { 70 | var method = SupportedMethods.FirstOrDefault(m => m.Name == expressionMethod.Name); 71 | if (method == null) 72 | { 73 | throw new NotSupportedException($"OpCode '{expressionMethod.Name}' not supported"); 74 | } 75 | 76 | var parameters = method.GetParameters(); 77 | object[] values = new object[parameters.Length]; 78 | values[0] = emitter; 79 | if (parameters.Length > 1) 80 | { 81 | for (int i = 1; i < parameters.Length; i++) 82 | { 83 | values[i] = arguments.Pop(); 84 | } 85 | } 86 | 87 | method.Invoke(null, values); 88 | } 89 | } 90 | else 91 | { 92 | emitter.Call(expressionMethod); 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /src/FluentIL/Expressions/ICondition.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Expressions 2 | { 3 | /// 4 | /// Defines the condition interface. 5 | /// 6 | public interface ICondition 7 | { 8 | /// 9 | /// Loads a local value onto the top of the evaluation stack. 10 | /// 11 | /// The local type. 12 | /// A reference to a local. 13 | /// The local value. 14 | T LdLoc(ILocal local); 15 | 16 | /// 17 | /// Loads the value from local at position 0 onto the top of the evaluation stack. 18 | /// 19 | /// The local type. 20 | /// The local value.l 21 | T LdLoc0(); 22 | 23 | /// 24 | /// Loads the value from local at position 1 onto the top of the evaluation stack. 25 | /// 26 | /// The local type. 27 | /// The local value. 28 | T LdLoc1(); 29 | 30 | /// 31 | /// Loads the value from local at position 2 onto the top of the evaluation stack. 32 | /// 33 | /// The local type. 34 | /// The local value. 35 | T LdLoc2(); 36 | 37 | /// 38 | /// Loads the value from local at position 3 onto the top of the evaluation stack. 39 | /// 40 | /// The local type. 41 | /// The local value. 42 | T LdLoc3(); 43 | 44 | /// 45 | /// Loads an integer value onto the top of the evaluation stack. 46 | /// 47 | /// The value to load. 48 | /// The value. 49 | int LdcI4(int value); 50 | 51 | /// 52 | /// Loads an integer value 0 onto the top of the evaluation stack. 53 | /// 54 | /// The value. 55 | int LdcI4_0(); 56 | 57 | /// 58 | /// Loads an integer value 1 onto the top of the evaluation stack. 59 | /// 60 | /// The value. 61 | int LdcI4_1(); 62 | 63 | /// 64 | /// Loads an integer value 2 onto the top of the evaluation stack. 65 | /// 66 | /// The value. 67 | int LdcI4_2(); 68 | 69 | /// 70 | /// Loads an integer value 3 onto the top of the evaluation stack. 71 | /// 72 | /// The value. 73 | int LdcI4_3(); 74 | 75 | /// 76 | /// Loads an integer value 4 onto the top of the evaluation stack. 77 | /// 78 | /// The value. 79 | int LdcI4_4(); 80 | 81 | /// 82 | /// Loads an integer value 5 onto the top of the evaluation stack. 83 | /// 84 | /// The value. 85 | int LdcI4_5(); 86 | 87 | /// 88 | /// Loads an integer value 6 onto the top of the evaluation stack. 89 | /// 90 | /// The value. 91 | int LdcI4_6(); 92 | 93 | /// 94 | /// Loads an integer value 7 onto the top of the evaluation stack. 95 | /// 96 | /// The value. 97 | int LdcI4_7(); 98 | 99 | /// 100 | /// Loads an integer value 8 onto the top of the evaluation stack. 101 | /// 102 | /// The value. 103 | int LdcI4_8(); 104 | } 105 | } -------------------------------------------------------------------------------- /src/FluentIL/Expressions/IInitialiser.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL.Expressions 2 | { 3 | /// 4 | /// Defines the intialiser interface. 5 | /// 6 | public interface IInitialiser 7 | { 8 | /// 9 | /// Declares a local. 10 | /// 11 | /// The locals type. 12 | /// A variable to receive a local. 13 | /// The instance. 14 | IInitialiser DeclareLocal(out ILocal local); 15 | 16 | /// 17 | /// Declares a local. 18 | /// 19 | /// The locals type. 20 | /// The name of the local. 21 | /// A variable to receive a local. 22 | /// The instance. 23 | IInitialiser DeclareLocal(string localName, out ILocal local); 24 | 25 | /// 26 | /// Loads a local value onto the top of the evaluation stack. 27 | /// 28 | /// A reference to a local. 29 | /// The instance. 30 | IInitialiser LdLoc(ILocal local); 31 | 32 | /// 33 | /// Stores the value on the top of the evaluation stack in the local. 34 | /// 35 | /// A reference to a local. 36 | /// The instance. 37 | IInitialiser StLoc(ILocal local); 38 | 39 | /// 40 | /// Loads an value on the top of the evaluation stack. 41 | /// 42 | /// The value. 43 | /// The instance. 44 | IInitialiser LdcI4(int value); 45 | 46 | /// 47 | /// Loads the value 0 on the top of the evaluation stack. 48 | /// 49 | /// The instance. 50 | IInitialiser LdcI4_0(); 51 | 52 | /// 53 | /// Loads the value 1 on the top of the evaluation stack. 54 | /// 55 | /// The instance. 56 | IInitialiser LdcI4_1(); 57 | 58 | /// 59 | /// Loads the value 2 on the top of the evaluation stack. 60 | /// 61 | /// The instance. 62 | IInitialiser LdcI4_2(); 63 | 64 | /// 65 | /// Loads the value 3 on the top of the evaluation stack. 66 | /// 67 | /// The instance. 68 | IInitialiser LdcI4_3(); 69 | 70 | /// 71 | /// Loads the value 4 on the top of the evaluation stack. 72 | /// 73 | /// The instance. 74 | IInitialiser LdcI4_4(); 75 | 76 | /// 77 | /// Loads the value 5 on the top of the evaluation stack. 78 | /// 79 | /// The instance. 80 | IInitialiser LdcI4_5(); 81 | 82 | /// 83 | /// Loads the value 6 on the top of the evaluation stack. 84 | /// 85 | /// The instance. 86 | IInitialiser LdcI4_6(); 87 | 88 | /// 89 | /// Loads the value 7 on the top of the evaluation stack. 90 | /// 91 | /// The instance. 92 | IInitialiser LdcI4_7(); 93 | 94 | /// 95 | /// Loads the value 8 on the top of the evaluation stack. 96 | /// 97 | /// The instance. 98 | IInitialiser LdcI4_8(); 99 | 100 | /// 101 | /// Loads the value minus one on the top of the evaluation stack. 102 | /// 103 | /// The instance. 104 | IInitialiser LdcI4_M1(); 105 | 106 | /// 107 | /// Loads an value on the top of the evaluation stack. 108 | /// 109 | /// The value. 110 | /// The instance. 111 | IInitialiser LdcI8(int value); 112 | 113 | /// 114 | /// Loads an value on the top of the evaluation stack. 115 | /// 116 | /// The value. 117 | /// The instance. 118 | IInitialiser LdcR4(float value); 119 | 120 | /// 121 | /// Loads an value on the top of the evaluation stack. 122 | /// 123 | /// The value. 124 | /// The instance. 125 | IInitialiser LdcR8(double value); 126 | } 127 | } -------------------------------------------------------------------------------- /src/FluentIL/Extensions/ConstructorBuilderExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using FluentIL.Emitters; 6 | 7 | /// 8 | /// and extension methods. 9 | /// 10 | public static class ConstructorBuilderExtensionMethods 11 | { 12 | /// 13 | /// Adds the 'Public' attribute to the constructor. 14 | /// 15 | /// A instance. 16 | /// The instance. 17 | public static IConstructorBuilder Public(this IConstructorBuilder builder) 18 | { 19 | builder.MethodAttributes |= MethodAttributes.Public; 20 | return builder; 21 | } 22 | 23 | /// 24 | /// Adds the 'Private' attribute to the constructor. 25 | /// 26 | /// A instance. 27 | /// The instance. 28 | public static IConstructorBuilder Private(this IConstructorBuilder builder) 29 | { 30 | builder.MethodAttributes |= MethodAttributes.Private; 31 | return builder; 32 | } 33 | 34 | /// 35 | /// Adds the 'HideBySig' attribute to the constructor. 36 | /// 37 | /// A instance. 38 | /// The instance. 39 | public static IConstructorBuilder HideBySig(this IConstructorBuilder builder) 40 | { 41 | builder.MethodAttributes |= MethodAttributes.HideBySig; 42 | return builder; 43 | } 44 | 45 | /// 46 | /// Adds the 'Assembly' attribute to the constructor. 47 | /// 48 | /// A instance. 49 | /// The instance. 50 | public static IConstructorBuilder Assembly(this IConstructorBuilder builder) 51 | { 52 | builder.MethodAttributes |= MethodAttributes.Assembly; 53 | return builder; 54 | } 55 | 56 | /// 57 | /// Adds the 'FamANDAssembly' attribute to the constructor. 58 | /// 59 | /// A instance. 60 | /// The instance. 61 | public static IConstructorBuilder FamANDAssem(this IConstructorBuilder builder) 62 | { 63 | builder.MethodAttributes |= MethodAttributes.FamANDAssem; 64 | return builder; 65 | } 66 | 67 | /// 68 | /// Adds the 'Family' attribute to the constructor. 69 | /// 70 | /// A instance. 71 | /// The instance. 72 | public static IConstructorBuilder Family(this IConstructorBuilder builder) 73 | { 74 | builder.MethodAttributes |= MethodAttributes.Family; 75 | return builder; 76 | } 77 | 78 | /// 79 | /// Adds the 'FamORAssem' attribute to the constructor. 80 | /// 81 | /// A instance. 82 | /// The instance. 83 | public static IConstructorBuilder FamORAssem(this IConstructorBuilder builder) 84 | { 85 | builder.MethodAttributes |= MethodAttributes.FamORAssem; 86 | return builder; 87 | } 88 | 89 | /// 90 | /// Adds the 'SpecialName' attribute to the constructor. 91 | /// 92 | /// A instance. 93 | /// The instance. 94 | public static IConstructorBuilder SpecialName(this IConstructorBuilder builder) 95 | { 96 | builder.MethodAttributes |= MethodAttributes.SpecialName; 97 | return builder; 98 | } 99 | 100 | /// 101 | /// Adds the 'RTSpecialName' attribute to the constructor. 102 | /// 103 | /// A instance. 104 | /// The instance. 105 | public static IConstructorBuilder RTSpecialName(this IConstructorBuilder builder) 106 | { 107 | builder.MethodAttributes |= MethodAttributes.RTSpecialName; 108 | return builder; 109 | } 110 | 111 | /// 112 | /// Defines the constructor as static. 113 | /// 114 | /// A instance. 115 | /// The instance. 116 | public static IConstructorBuilder Static(this IConstructorBuilder builder) 117 | { 118 | builder.CallingConvention(CallingConventions.Standard); 119 | return builder; 120 | } 121 | 122 | /// 123 | /// Adds a parameter. 124 | /// 125 | /// The parameter type. 126 | /// A instance. 127 | /// The parameter name. 128 | /// The instance. 129 | public static IConstructorBuilder Param(this IConstructorBuilder builder, string parameterName) 130 | { 131 | builder.Param(typeof(T), parameterName); 132 | return builder; 133 | } 134 | 135 | /// 136 | /// Returns a to define the constructors body. 137 | /// 138 | /// A instance. 139 | /// An instance. 140 | public static IEmitter Body(this ConstructorBuilder constructorBuilder) 141 | { 142 | DebugOutput.WriteLine("Body:"); 143 | 144 | var emitter = new ILGeneratorEmitter(constructorBuilder.GetILGenerator()); 145 | if (DebugOutput.Output == null) 146 | { 147 | return emitter; 148 | } 149 | 150 | return new DebugEmitter(emitter, DebugOutput.Output); 151 | } 152 | } 153 | } -------------------------------------------------------------------------------- /src/FluentIL/Extensions/DynamicMethodExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | 5 | /// 6 | /// extension methods. 7 | /// 8 | public static class DynamicMethodExtensionMethods 9 | { 10 | /// 11 | /// Defines the method. 12 | /// 13 | /// The dynamic method builder. 14 | /// The delegates type. 15 | /// The instance. 16 | public static Delegate Create(this IDynamicMethodBuilder dynamicMethodBuilder, Type delegateType) 17 | { 18 | return dynamicMethodBuilder.Define().CreateDelegate(delegateType); 19 | } 20 | 21 | /// 22 | /// Creates the action. 23 | /// 24 | /// The dynamic method builder. 25 | /// The instance. 26 | public static Action CreateAction(this IDynamicMethodBuilder dynamicMethodBuilder) 27 | { 28 | return (Action)dynamicMethodBuilder.Define().CreateDelegate(typeof(Action)); 29 | } 30 | 31 | /// 32 | /// Creates the action. 33 | /// 34 | /// The parameter type. 35 | /// The dynamic method builder. 36 | /// The instance. 37 | public static Action CreateAction(this IDynamicMethodBuilder dynamicMethodBuilder) 38 | { 39 | return (Action)dynamicMethodBuilder.Define().CreateDelegate(typeof(Action)); 40 | } 41 | 42 | /// 43 | /// Creates the action. 44 | /// 45 | /// The first parameter type. 46 | /// The second parameter type. 47 | /// The dynamic method builder. 48 | /// The instance. 49 | public static Action CreateAction(this IDynamicMethodBuilder dynamicMethodBuilder) 50 | { 51 | return (Action)dynamicMethodBuilder.Define().CreateDelegate(typeof(Action)); 52 | } 53 | 54 | /// 55 | /// Creates the action. 56 | /// 57 | /// The first parameter type. 58 | /// The second parameter type. 59 | /// The third parameter type. 60 | /// The dynamic method builder. 61 | /// The instance. 62 | public static Action CreateAction(this IDynamicMethodBuilder dynamicMethodBuilder) 63 | { 64 | return (Action)dynamicMethodBuilder.Define().CreateDelegate(typeof(Action)); 65 | } 66 | 67 | /// 68 | /// Creates the function. 69 | /// 70 | /// The return type. 71 | /// The dynamic method builder. 72 | /// The instance. 73 | public static Func CreateFunc(this IDynamicMethodBuilder dynamicMethodBuilder) 74 | { 75 | return (Func)dynamicMethodBuilder.Define().CreateDelegate(typeof(Func)); 76 | } 77 | 78 | /// 79 | /// Creates the function. 80 | /// 81 | /// The parameter type. 82 | /// The return type. 83 | /// The dynamic method builder. 84 | /// The instance. 85 | public static Func CreateFunc(this IDynamicMethodBuilder dynamicMethodBuilder) 86 | { 87 | return (Func)dynamicMethodBuilder.Define().CreateDelegate(typeof(Func)); 88 | } 89 | 90 | /// 91 | /// Creates the function. 92 | /// 93 | /// The first parameter type. 94 | /// The second parameter type. 95 | /// The return type. 96 | /// The dynamic method builder. 97 | /// The instance. 98 | public static Func CreateFunc(this IDynamicMethodBuilder dynamicMethodBuilder) 99 | { 100 | return (Func)dynamicMethodBuilder.Define().CreateDelegate(typeof(Func)); 101 | } 102 | 103 | /// 104 | /// Creates the function. 105 | /// 106 | /// The first parameter type. 107 | /// The second parameter type. 108 | /// The third parameter type. 109 | /// The return type. 110 | /// The dynamic method builder. 111 | /// The instance. 112 | public static Func CreateFunc(this IDynamicMethodBuilder dynamicMethodBuilder) 113 | { 114 | return (Func)dynamicMethodBuilder.Define().CreateDelegate(typeof(Func)); 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /src/FluentIL/Extensions/EmitterLdcExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | 6 | /// 7 | /// Load constant extension methods. 8 | /// 9 | public static class EmitterLdcExtensions 10 | { 11 | /// 12 | /// Emits the IL to push a supplied value onto the top of the evaluation stack. 13 | /// 14 | /// An instance. 15 | /// The value to load. 16 | /// The . 17 | public static IEmitter LdcI4(this IEmitter emitter, int value) 18 | { 19 | return emitter.Emit(OpCodes.Ldc_I4, value); 20 | } 21 | 22 | /// 23 | /// Emits the IL to push the value 0 onto the top of the evaluation stack. 24 | /// 25 | /// An instance. 26 | /// The instance. 27 | public static IEmitter LdcI4_0(this IEmitter emitter) 28 | { 29 | return emitter.Emit(OpCodes.Ldc_I4_0); 30 | } 31 | 32 | /// 33 | /// Emits the IL to push the value 1 onto the top of the evaluation stack. 34 | /// 35 | /// An instance. 36 | /// The instance. 37 | public static IEmitter LdcI4_1(this IEmitter emitter) 38 | { 39 | return emitter.Emit(OpCodes.Ldc_I4_1); 40 | } 41 | 42 | /// 43 | /// Emits the IL to push the value 2 onto the top of the evaluation stack. 44 | /// 45 | /// An instance. 46 | /// The instance. 47 | public static IEmitter LdcI4_2(this IEmitter emitter) 48 | { 49 | return emitter.Emit(OpCodes.Ldc_I4_2); 50 | } 51 | 52 | /// 53 | /// Emits the IL to push the value 3 onto the top of the evaluation stack. 54 | /// 55 | /// An instance. 56 | /// The instance. 57 | public static IEmitter LdcI4_3(this IEmitter emitter) 58 | { 59 | return emitter.Emit(OpCodes.Ldc_I4_3); 60 | } 61 | 62 | /// 63 | /// Emits the IL to push the value 4 onto the top of the evaluation stack. 64 | /// 65 | /// An instance. 66 | /// The instance. 67 | public static IEmitter LdcI4_4(this IEmitter emitter) 68 | { 69 | return emitter.Emit(OpCodes.Ldc_I4_4); 70 | } 71 | 72 | /// 73 | /// Emits the IL to push the value 5 onto the top of the evaluation stack. 74 | /// 75 | /// An instance. 76 | /// The instance. 77 | public static IEmitter LdcI4_5(this IEmitter emitter) 78 | { 79 | return emitter.Emit(OpCodes.Ldc_I4_5); 80 | } 81 | 82 | /// 83 | /// Emits the IL to push the value 6 onto the top of the evaluation stack. 84 | /// 85 | /// An instance. 86 | /// The instance. 87 | public static IEmitter LdcI4_6(this IEmitter emitter) 88 | { 89 | return emitter.Emit(OpCodes.Ldc_I4_6); 90 | } 91 | 92 | /// 93 | /// Emits the IL to push the value 7 onto the top of the evaluation stack. 94 | /// 95 | /// An instance. 96 | /// The instance. 97 | public static IEmitter LdcI4_7(this IEmitter emitter) 98 | { 99 | return emitter.Emit(OpCodes.Ldc_I4_7); 100 | } 101 | 102 | /// 103 | /// Emits the IL to push the value 8 onto the top of the evaluation stack. 104 | /// 105 | /// An instance. 106 | /// The instance. 107 | public static IEmitter LdcI4_8(this IEmitter emitter) 108 | { 109 | return emitter.Emit(OpCodes.Ldc_I4_8); 110 | } 111 | 112 | /// 113 | /// Pushes the integer value of -1 onto the evaluation stack as an int32. 114 | /// 115 | /// An instance. 116 | /// The instance. 117 | public static IEmitter LdcI4_M1(this IEmitter emitter) 118 | { 119 | return emitter.Emit(OpCodes.Ldc_I4_M1); 120 | } 121 | 122 | /// 123 | /// Pushes the supplied int8 value onto the evaluation stack as an int32, short form. 124 | /// 125 | /// An instance. 126 | /// A value. 127 | /// The instance. 128 | public static IEmitter LdcI4_S(this IEmitter emitter, byte value) 129 | { 130 | return emitter.Emit(OpCodes.Ldc_I4_S, value); 131 | } 132 | 133 | /// 134 | /// Pushes a supplied value of type int64 onto the evaluation stack as an int64. 135 | /// 136 | /// An instance. 137 | /// A value. 138 | /// The instance. 139 | public static IEmitter LdcI8(this IEmitter emitter, long value) 140 | { 141 | return emitter.Emit(OpCodes.Ldc_I8, value); 142 | } 143 | 144 | /// 145 | /// Pushes a supplied value of type float32 onto the evaluation stack as type F (float). 146 | /// 147 | /// An instance. 148 | /// A value. 149 | /// The instance. 150 | public static IEmitter LdcR4(this IEmitter emitter, float value) 151 | { 152 | return emitter.Emit(OpCodes.Ldc_R4, value); 153 | } 154 | 155 | /// 156 | /// Pushes a supplied value of type float64 onto the evaluation stack as type F (float). 157 | /// 158 | /// An instance. 159 | /// A value. 160 | /// The instance. 161 | public static IEmitter LdcR8(this IEmitter emitter, double value) 162 | { 163 | return emitter.Emit(OpCodes.Ldc_R8, value); 164 | } 165 | } 166 | } -------------------------------------------------------------------------------- /src/FluentIL/Extensions/FieldBuilderExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System.Reflection; 4 | 5 | /// 6 | /// extension methods. 7 | /// 8 | public static class FieldBuilderExtensionMethods 9 | { 10 | /// 11 | /// Specifies that the field is accessible only by the parent type. 12 | /// 13 | /// A instance. 14 | /// The instance. 15 | public static IFieldBuilder Private(this IFieldBuilder builder) 16 | { 17 | builder.FieldAttributes |= FieldAttributes.Private; 18 | return builder; 19 | } 20 | 21 | /// 22 | /// Specifies that the field is accessible only by subtypes in this assembly. 23 | /// 24 | /// A instance. 25 | /// The instance. 26 | public static IFieldBuilder FamANDAssem(this IFieldBuilder builder) 27 | { 28 | builder.FieldAttributes |= FieldAttributes.FamANDAssem; 29 | return builder; 30 | } 31 | 32 | /// 33 | /// Specifies that the field is accessible throughout the assembly. 34 | /// 35 | /// A instance. 36 | /// The instance. 37 | public static IFieldBuilder Assembly(this IFieldBuilder builder) 38 | { 39 | builder.FieldAttributes |= FieldAttributes.Assembly; 40 | return builder; 41 | } 42 | 43 | /// 44 | /// Specifies that the field is accessible only by type and subtypes. 45 | /// 46 | /// A instance. 47 | /// The instance. 48 | public static IFieldBuilder Family(this IFieldBuilder builder) 49 | { 50 | builder.FieldAttributes |= FieldAttributes.Family; 51 | return builder; 52 | } 53 | 54 | /// 55 | /// Specifies that the field is accessible by subtypes anywhere, as well as throughout 56 | /// this assembly. 57 | /// 58 | /// A instance. 59 | /// The instance. 60 | public static IFieldBuilder FamORAssem(this IFieldBuilder builder) 61 | { 62 | builder.FieldAttributes |= FieldAttributes.FamORAssem; 63 | return builder; 64 | } 65 | 66 | /// 67 | /// Specifies that the field is accessible by any member for whom this scope is visible. 68 | /// 69 | /// A instance. 70 | /// The instance. 71 | public static IFieldBuilder Public(this IFieldBuilder builder) 72 | { 73 | builder.FieldAttributes = (builder.FieldAttributes & ~FieldAttributes.Private) | FieldAttributes.Public; 74 | return builder; 75 | } 76 | 77 | /// 78 | /// Specifies that the field represents the defined type, or else it is per-instance. 79 | /// 80 | /// A instance. 81 | /// The instance. 82 | public static IFieldBuilder Static(this IFieldBuilder builder) 83 | { 84 | builder.FieldAttributes |= FieldAttributes.Static; 85 | return builder; 86 | } 87 | 88 | /// 89 | /// Specifies that the field is initialized only, and can be set only in the body 90 | /// of a constructor. 91 | /// 92 | /// A instance. 93 | /// The instance. 94 | public static IFieldBuilder InitOnly(this IFieldBuilder builder) 95 | { 96 | builder.FieldAttributes |= FieldAttributes.InitOnly; 97 | return builder; 98 | } 99 | 100 | /// 101 | /// Specifies that the field's value is a compile-time (static or early bound) constant. 102 | /// Any attempt to set it throws a System.FieldAccessException. 103 | /// 104 | /// A instance. 105 | /// The instance. 106 | public static IFieldBuilder Literal(this IFieldBuilder builder) 107 | { 108 | builder.FieldAttributes |= FieldAttributes.Literal; 109 | return builder; 110 | } 111 | 112 | /// 113 | /// Specifies that the field does not have to be serialized when the type is remoted. 114 | /// 115 | /// A instance. 116 | /// The instance. 117 | public static IFieldBuilder NotSerialized(this IFieldBuilder builder) 118 | { 119 | builder.FieldAttributes |= FieldAttributes.NotSerialized; 120 | return builder; 121 | } 122 | 123 | /// 124 | /// Specifies that the field has a relative virtual address (RVA). The RVA is the 125 | /// location of the method body in the current image, as an address relative to the 126 | /// start of the image file in which it is located. 127 | /// 128 | /// A instance. 129 | /// The instance. 130 | public static IFieldBuilder HasFieldRVA(this IFieldBuilder builder) 131 | { 132 | builder.FieldAttributes |= FieldAttributes.HasFieldRVA; 133 | return builder; 134 | } 135 | 136 | /// 137 | /// Specifies a special method, with the name describing how the method is special. 138 | /// 139 | /// A instance. 140 | /// The instance. 141 | public static IFieldBuilder SpecialName(this IFieldBuilder builder) 142 | { 143 | builder.FieldAttributes |= FieldAttributes.SpecialName; 144 | return builder; 145 | } 146 | 147 | /// 148 | /// Specifies that the common language runtime (metadata internal APIs) should check 149 | /// the name encoding. 150 | /// 151 | /// A instance. 152 | /// The instance. 153 | public static IFieldBuilder RTSpecialName(this IFieldBuilder builder) 154 | { 155 | builder.FieldAttributes |= FieldAttributes.RTSpecialName; 156 | return builder; 157 | } 158 | 159 | /// 160 | /// Specifies that the field has marshaling information. 161 | /// 162 | /// A instance. 163 | /// The instance. 164 | public static IFieldBuilder HasFieldMarshal(this IFieldBuilder builder) 165 | { 166 | builder.FieldAttributes |= FieldAttributes.HasFieldMarshal; 167 | return builder; 168 | } 169 | 170 | /// 171 | /// Specifies that the field has a default value. 172 | /// 173 | /// A instance. 174 | /// The instance. 175 | public static IFieldBuilder HasDefault(this IFieldBuilder builder) 176 | { 177 | builder.FieldAttributes |= FieldAttributes.HasDefault; 178 | return builder; 179 | } 180 | } 181 | } -------------------------------------------------------------------------------- /src/FluentIL/Extensions/MethodBuilderExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using FluentIL.Emitters; 6 | 7 | /// 8 | /// and extension methods. 9 | /// 10 | public static class MethodBuilderExtensionMethods 11 | { 12 | /// 13 | /// Indicates that the method is accessible to any object for which this object is in scope. 14 | /// 15 | /// A instance. 16 | /// The instance. 17 | public static IMethodBuilder Public(this IMethodBuilder builder) 18 | { 19 | builder.Attributes |= MethodAttributes.Public; 20 | return builder; 21 | } 22 | 23 | /// 24 | /// Indicates that the method is accessible only to the current class. 25 | /// 26 | /// A instance. 27 | /// The instance. 28 | public static IMethodBuilder Private(this IMethodBuilder builder) 29 | { 30 | builder.Attributes |= MethodAttributes.Private; 31 | return builder; 32 | } 33 | 34 | /// 35 | /// Indicates that the method is virtual. 36 | /// 37 | /// A instance. 38 | /// The instance. 39 | public static IMethodBuilder Virtual(this IMethodBuilder builder) 40 | { 41 | builder.Attributes |= MethodAttributes.Virtual; 42 | return builder; 43 | } 44 | 45 | /// 46 | /// Indicates that the method hides by name and signature; otherwise, by name only. 47 | /// 48 | /// A instance. 49 | /// The instance. 50 | public static IMethodBuilder HideBySig(this IMethodBuilder builder) 51 | { 52 | builder.Attributes |= MethodAttributes.HideBySig; 53 | return builder; 54 | } 55 | 56 | /// 57 | /// Indicates that the method. 58 | /// 59 | /// A instance. 60 | /// The instance. 61 | public static IMethodBuilder SpecialName(this IMethodBuilder builder) 62 | { 63 | builder.Attributes |= MethodAttributes.SpecialName; 64 | return builder; 65 | } 66 | 67 | /// 68 | /// Indicates that the method. 69 | /// 70 | /// A instance. 71 | /// The instance. 72 | public static IMethodBuilder RTSpecialName(this IMethodBuilder builder) 73 | { 74 | builder.Attributes |= MethodAttributes.RTSpecialName; 75 | return builder; 76 | } 77 | 78 | /// 79 | /// Indicates that the method always gets a new slot in the vtable. 80 | /// 81 | /// A instance. 82 | /// The instance. 83 | public static IMethodBuilder NewSlot(this IMethodBuilder builder) 84 | { 85 | builder.Attributes |= MethodAttributes.NewSlot; 86 | return builder; 87 | } 88 | 89 | /// 90 | /// Indicates that the method is defined on the type; otherwise, it is defined per instance. 91 | /// 92 | /// A instance. 93 | /// The instance. 94 | public static IMethodBuilder Static(this IMethodBuilder builder) 95 | { 96 | builder.Attributes |= MethodAttributes.Static; 97 | return builder; 98 | } 99 | 100 | /// 101 | /// Defines a parameter. 102 | /// 103 | /// The parameter type. 104 | /// A instance. 105 | /// The instance. 106 | public static IMethodBuilder Param(this IMethodBuilder methodBuilder) 107 | { 108 | return methodBuilder.Param(null); 109 | } 110 | 111 | /// 112 | /// Defines a parameter. 113 | /// 114 | /// The parameter type. 115 | /// A instance. 116 | /// The name of parameter. 117 | /// The parameters attribtes. 118 | /// The instance. 119 | public static IMethodBuilder Param(this IMethodBuilder methodBuilder, string parameterName, ParameterAttributes attrs = ParameterAttributes.None) 120 | { 121 | return methodBuilder.Param(typeof(TParam), parameterName, attrs); 122 | } 123 | 124 | /// 125 | /// Defines an out parameter. 126 | /// 127 | /// The parameter type. 128 | /// A instance. 129 | /// The name of parameter. 130 | /// The instance. 131 | public static IMethodBuilder OutParam(this IMethodBuilder methodBuilder, string parameterName) 132 | { 133 | return methodBuilder.Param(typeof(TParam).MakeByRefType(), parameterName, ParameterAttributes.Out); 134 | } 135 | 136 | /// 137 | /// Defines an ref parameter. 138 | /// 139 | /// The parameter type. 140 | /// A instance. 141 | /// The name of parameter. 142 | /// The instance. 143 | public static IMethodBuilder RefParam(this IMethodBuilder methodBuilder, string parameterName) 144 | { 145 | return methodBuilder.Param(typeof(TParam).MakeByRefType(), parameterName, ParameterAttributes.None); 146 | } 147 | 148 | /// 149 | /// Returns a for the method body. 150 | /// 151 | /// A instance. 152 | /// An instance. 153 | public static IEmitter Body(this MethodBuilder methodBuilder) 154 | { 155 | DebugOutput.WriteLine("Body:"); 156 | 157 | var emitter = new ILGeneratorEmitter(methodBuilder.GetILGenerator()); 158 | if (DebugOutput.Output == null) 159 | { 160 | return emitter; 161 | } 162 | 163 | return new DebugEmitter(emitter, DebugOutput.Output); 164 | } 165 | } 166 | } -------------------------------------------------------------------------------- /src/FluentIL/Extensions/ParameterInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | /// 8 | /// Extensions to the class. 9 | /// 10 | public static class ParameterInfoExtensions 11 | { 12 | /// 13 | /// Checks if a parameter has an attribute applied to it. 14 | /// 15 | /// The parameter. 16 | /// The attribute type. 17 | /// True if it has; otherwise false. 18 | public static bool HasAttribute(this ParameterInfo parameterInfo, Type attributeType) 19 | { 20 | return parameterInfo.GetCustomAttributes(attributeType).FirstOrDefault() != null; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/FluentIL/Extensions/TypeBuilderExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Reflection; 5 | 6 | /// 7 | /// extension methods. 8 | /// 9 | public static class TypeBuilderExtensionMethods 10 | { 11 | /// 12 | /// Specifies that the type is public. 13 | /// 14 | /// A type builder. 15 | /// The type builder instance. 16 | public static ITypeBuilder Public(this ITypeBuilder typeBuilder) 17 | { 18 | typeBuilder.TypeAttributes |= TypeAttributes.Public; 19 | return typeBuilder; 20 | } 21 | 22 | /// 23 | /// Specifies that the type is not public. 24 | /// 25 | /// A type builder. 26 | /// The type builder instance. 27 | public static ITypeBuilder NotPublic(this ITypeBuilder typeBuilder) 28 | { 29 | typeBuilder.TypeAttributes |= TypeAttributes.NotPublic; 30 | return typeBuilder; 31 | } 32 | 33 | /// 34 | /// Specifies that the type is a class. 35 | /// 36 | /// A type builder. 37 | /// A field builder. 38 | public static ITypeBuilder Class(this ITypeBuilder typeBuilder) 39 | { 40 | typeBuilder.TypeAttributes |= TypeAttributes.Class; 41 | return typeBuilder; 42 | } 43 | 44 | /// 45 | /// Specifies that the type is sealed. 46 | /// 47 | /// A type builder. 48 | /// A field builder. 49 | public static ITypeBuilder Sealed(this ITypeBuilder typeBuilder) 50 | { 51 | typeBuilder.TypeAttributes |= TypeAttributes.Sealed; 52 | return typeBuilder; 53 | } 54 | 55 | /// 56 | /// Specifies that the type is an interface. 57 | /// 58 | /// A type builder. 59 | /// A field builder. 60 | public static ITypeBuilder Interface(this ITypeBuilder typeBuilder) 61 | { 62 | typeBuilder.TypeAttributes |= TypeAttributes.Interface; 63 | return typeBuilder; 64 | } 65 | 66 | /// 67 | /// Specifies that the type is abstract. 68 | /// 69 | /// A type builder. 70 | /// A field builder. 71 | public static ITypeBuilder Abstract(this ITypeBuilder typeBuilder) 72 | { 73 | typeBuilder.TypeAttributes |= TypeAttributes.Abstract; 74 | return typeBuilder; 75 | } 76 | 77 | /// 78 | /// Specifies that calling static methods on the type does not force the system 79 | /// to initialize the type. 80 | /// 81 | /// A type builder. 82 | /// A field builder. 83 | public static ITypeBuilder BeforeFieldInit(this ITypeBuilder typeBuilder) 84 | { 85 | typeBuilder.TypeAttributes |= TypeAttributes.BeforeFieldInit; 86 | return typeBuilder; 87 | } 88 | 89 | /// 90 | /// Creates a field. 91 | /// 92 | /// The field type. 93 | /// A type builder. 94 | /// The name of the field. 95 | /// A field builder. 96 | public static IFieldBuilder NewField(this ITypeBuilder typeBuilder, string fieldName) 97 | { 98 | return typeBuilder.NewField(fieldName, typeof(T)); 99 | } 100 | 101 | /// 102 | /// Creates a property. 103 | /// 104 | /// The property type. 105 | /// A type builder. 106 | /// The name of the property. 107 | /// A properrty builder. 108 | public static IPropertyBuilder NewProperty(this ITypeBuilder typeBuilder, string propertyName) 109 | { 110 | return typeBuilder.NewProperty(propertyName, typeof(T)); 111 | } 112 | 113 | /// 114 | /// Creates a method. 115 | /// 116 | /// The return type. 117 | /// A type builder. 118 | /// The name of the method. 119 | /// A method builder instance. 120 | public static IMethodBuilder NewMethod(this ITypeBuilder typeBuilder, string name) 121 | { 122 | return typeBuilder.NewMethod( 123 | name, 124 | MethodAttributes.Public, 125 | CallingConventions.HasThis, 126 | typeof(TReturn)); 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /src/FluentIL/Extensions/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | /// 9 | /// Extensions to Type and Object classes. 10 | /// 11 | public static class TypeExtensions 12 | { 13 | /// 14 | /// Checks if an object has a name property. 15 | /// 16 | /// The object to check. 17 | /// The name of the property. 18 | /// True if the object has the property; otherwise false. 19 | public static bool HasProperty(this object obj, string propertyName) 20 | { 21 | if (obj != null) 22 | { 23 | return obj.GetType().GetProperty(propertyName) != null; 24 | } 25 | 26 | return false; 27 | } 28 | 29 | /// 30 | /// Gets the value of a named property. 31 | /// 32 | /// The object which has the property. 33 | /// The name of the property. 34 | /// The property value. 35 | public static object GetPropertyValue(this object obj, string propertyName) 36 | { 37 | if (obj != null) 38 | { 39 | PropertyInfo pi = obj.GetType().GetProperty(propertyName); 40 | if (pi != null) 41 | { 42 | return pi.GetValue(obj); 43 | } 44 | } 45 | 46 | return null; 47 | } 48 | 49 | /// 50 | /// Sets the value of a named property. 51 | /// 52 | /// The object to set the property on. 53 | /// The name of the property to set. 54 | /// The value to set the property to. 55 | public static void SetPropertyValue(this object obj, string propertyName, object propertyValue) 56 | { 57 | if (obj != null) 58 | { 59 | PropertyInfo pi = obj.GetType().GetProperty(propertyName); 60 | if (pi != null) 61 | { 62 | pi.SetValue(obj, propertyValue); 63 | } 64 | } 65 | } 66 | 67 | /// 68 | /// Returns the representation an object as a string containing the properties with values. 69 | /// 70 | /// The object. 71 | /// String containing the object property values. 72 | public static string PropertyValuesAsString(this object obj) 73 | { 74 | string ret = string.Empty; 75 | const string Separator = ", "; 76 | 77 | foreach (PropertyInfo info in obj.GetType().GetProperties()) 78 | { 79 | object value = obj.GetPropertyValue(info.Name); 80 | if (value != null) 81 | { 82 | if (ret.Length > 0) 83 | { 84 | ret += Separator; 85 | } 86 | 87 | ret += info.Name + ": " + value.ToString(); 88 | } 89 | } 90 | 91 | return ret; 92 | } 93 | 94 | /// 95 | /// Checks if an list is null or empty. 96 | /// 97 | /// The list type. 98 | /// The list instance. 99 | /// True if the list is null or empty. 100 | public static bool IsNullOrEmpty(this IEnumerable list) 101 | { 102 | return list == null || list.Any() == false; 103 | } 104 | 105 | /// 106 | /// Checks if a is null or empty. 107 | /// 108 | /// The dictionary key type. 109 | /// The dictionary value type. 110 | /// The dictionary instance. 111 | /// True if the dictionary is null or empty. 112 | public static bool IsNullOrEmpty(this IDictionary dictionary) 113 | { 114 | return dictionary == null || dictionary.Any() == false; 115 | } 116 | 117 | /// 118 | /// Checks if a is a delegate. 119 | /// 120 | /// The type to check. 121 | /// True if it is; otherwise false. 122 | public static bool IsDelegate(this Type type) 123 | { 124 | return type != null && 125 | typeof(Delegate).IsAssignableFrom(type); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/FluentIL/FluentIL.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 1.0.1 5 | Fluent.IL 6 | pcol 7 | Fluent.IL 8 | A fluent IL helper library. 9 | Initial release 10 | reflection emit il 11 | https://github.com/PCOL/FluentIL 12 | MIT 13 | netstandard1.6;netstandard2.0;net5.0 14 | portable 15 | FluentIL 16 | ../../ca.ruleset 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | all 35 | runtime; build; native; contentfiles; analyzers 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/FluentIL/FluentIL.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.002.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentIL", "FluentIL.csproj", "{406C1558-FE4F-411C-BB63-09444ED011C4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {406C1558-FE4F-411C-BB63-09444ED011C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {406C1558-FE4F-411C-BB63-09444ED011C4}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {406C1558-FE4F-411C-BB63-09444ED011C4}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {406C1558-FE4F-411C-BB63-09444ED011C4}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {634E09EB-43A8-4919-9AC0-33FEDBD08149} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/FluentIL/IAdaptedLabel.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | /// 4 | /// Defines the adapted label interface. 5 | /// 6 | internal interface IAdaptedLabel 7 | { 8 | /// 9 | /// Gets or sets the adapted label. 10 | /// 11 | object Label { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/FluentIL/IAdaptedLocal.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | /// 4 | /// Defines an adapted object. 5 | /// 6 | internal interface IAdaptedLocal 7 | { 8 | /// 9 | /// Gets or sets the adapted local object. 10 | /// 11 | object Local { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/FluentIL/IAssemblyBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | /// 4 | /// Defines the assembly builder interface. 5 | /// 6 | public interface IAssemblyBuilder 7 | { 8 | /// 9 | /// Creates a module. 10 | /// 11 | /// The name of the module. 12 | /// A instance. 13 | IModuleBuilder NewDynamicModule(string moduleName); 14 | } 15 | } -------------------------------------------------------------------------------- /src/FluentIL/IConstructorBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// Defines the Constructor builder interface. 9 | /// 10 | public interface IConstructorBuilder 11 | { 12 | /// 13 | /// Gets or sets the methods attributes. 14 | /// 15 | MethodAttributes MethodAttributes { get; set; } 16 | 17 | /// 18 | /// Gets the constructors body emitter. 19 | /// 20 | /// The instance. 21 | IEmitter Body(); 22 | 23 | /// 24 | /// Sets the constructors calling convention. 25 | /// 26 | /// The calling convention. 27 | /// The instance. 28 | IConstructorBuilder CallingConvention(CallingConventions callingConvention); 29 | 30 | /// 31 | /// Defines a constructor parameter. 32 | /// 33 | /// The parameters type. 34 | /// The name of the parameter. 35 | /// The parameters attributes. 36 | /// The instance. 37 | IConstructorBuilder Param(Type parameterType, string parameterName, ParameterAttributes attrs = ParameterAttributes.None); 38 | 39 | /// 40 | /// Defines a constructor parameter. 41 | /// 42 | /// The parameters generic type. 43 | /// The name of the parameter. 44 | /// The parameters attributes. 45 | /// The instance. 46 | IConstructorBuilder Param(IGenericParameterBuilder genericParameter, string parameterName, ParameterAttributes attrs = ParameterAttributes.None); 47 | 48 | /// 49 | /// Defines a constructor parameter. 50 | /// 51 | /// Parameter builder action. 52 | /// The instance. 53 | IConstructorBuilder Param(Action action); 54 | 55 | /// 56 | /// Defines the constructor parameters. 57 | /// 58 | /// The parameter types. 59 | /// The instance. 60 | IConstructorBuilder Params(params Type[] parameterTypes); 61 | 62 | /// 63 | /// Sets the constructors atrributes. 64 | /// 65 | /// The attributes. 66 | /// The instance. 67 | IConstructorBuilder SetMethodAttributes(MethodAttributes attributes); 68 | 69 | /// 70 | /// Sets the constructors implementation attributes. 71 | /// 72 | /// The attributes. 73 | /// The instance. 74 | IConstructorBuilder SetImplementationFlags(MethodImplAttributes attributes); 75 | 76 | /// 77 | /// Defines the constructor. 78 | /// 79 | /// A instance. 80 | ConstructorBuilder Define(); 81 | } 82 | } -------------------------------------------------------------------------------- /src/FluentIL/IDebugOutput.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | 5 | /// 6 | /// Defines the debug output interface. 7 | /// 8 | public interface IDebugOutput 9 | { 10 | /// 11 | /// Writes to debug output. 12 | /// 13 | /// A string format. 14 | /// The format arguments. 15 | void Write(string format, params object[] args); 16 | 17 | /// 18 | /// Writes a line to debug output. 19 | /// 20 | /// A string format. 21 | /// The format arguments. 22 | void WriteLine(string format, params object[] args); 23 | 24 | /// 25 | /// Writes to debug output in a specified colour. 26 | /// 27 | /// The colour of the string. 28 | /// A string format. 29 | /// The format arguments. 30 | void WriteColor(ConsoleColor color, string format, params object[] args); 31 | 32 | /// 33 | /// Writes a line to debug output in a specified colour. 34 | /// 35 | /// The colour of the string. 36 | /// A string format. 37 | /// The format arguments. 38 | void WriteLineColor(ConsoleColor color, string format, params object[] args); 39 | } 40 | } -------------------------------------------------------------------------------- /src/FluentIL/IDynamicMethodBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// Defines the dynamic method builder interface. 9 | /// 10 | public interface IDynamicMethodBuilder 11 | { 12 | /// 13 | /// Gets the methods body. 14 | /// 15 | /// The instance. 16 | IEmitter Body(); 17 | 18 | /// 19 | /// Provides access to the method body. 20 | /// 21 | /// An action to emit the body IL. 22 | /// The instance. 23 | IDynamicMethodBuilder Body(Action action); 24 | 25 | /// 26 | /// Sets the methods return type. 27 | /// 28 | /// The return type. 29 | /// The instance. 30 | IDynamicMethodBuilder Returns(); 31 | 32 | /// 33 | /// Sets the methods return type. 34 | /// 35 | /// The return type. 36 | /// The instance. 37 | IDynamicMethodBuilder Returns(Type returnType); 38 | 39 | /// 40 | /// Adds a parameter to the method. 41 | /// 42 | /// The parameters type. 43 | /// The parameters name. 44 | /// The parameters attributes. 45 | /// The instsnce. 46 | IDynamicMethodBuilder Param(string parameterName, ParameterAttributes attrs = ParameterAttributes.None); 47 | 48 | /// 49 | /// Adds a parameter to the method. 50 | /// 51 | /// The parameters type. 52 | /// The parameters name. 53 | /// The parameters attributes. 54 | /// The instsnce. 55 | IDynamicMethodBuilder Param(Type parameterType, string parameterName, ParameterAttributes attrs = ParameterAttributes.None); 56 | 57 | /// 58 | /// Adds a parameter to the method. 59 | /// 60 | /// A parameter builder action. 61 | /// The instance. 62 | IDynamicMethodBuilder Param(Action action); 63 | 64 | /// 65 | /// Adds a parameter to the method. 66 | /// 67 | /// A parameter builder. 68 | /// The instance. 69 | IDynamicMethodBuilder Param(IParameterBuilder parameter); 70 | 71 | /// 72 | /// Defines the methods parameters. 73 | /// 74 | /// The parameter types. 75 | /// The instance. 76 | IDynamicMethodBuilder Params(params Type[] parameterTypes); 77 | 78 | /// 79 | /// Defines the methods parameters. 80 | /// 81 | /// A list of parameter builders. 82 | /// The instance. 83 | IDynamicMethodBuilder Params(params IParameterBuilder[] parameters); 84 | 85 | /// 86 | /// Creates a parameter. 87 | /// 88 | /// The parameters type. 89 | /// The parameters name. 90 | /// The parameters attributes. 91 | /// The instsnce. 92 | IParameterBuilder CreateParam(string parameterName, ParameterAttributes attrs = ParameterAttributes.None); 93 | 94 | /// 95 | /// Creates a parameter. 96 | /// 97 | /// The parameters type. 98 | /// The parameters name. 99 | /// The parameters attribute. 100 | /// The instance. 101 | IParameterBuilder CreateParam(Type parameterType, string parameterName, ParameterAttributes attrs = ParameterAttributes.None); 102 | 103 | /// 104 | /// Defines the dynamic method. 105 | /// 106 | /// A instance. 107 | DynamicMethod Define(); 108 | } 109 | } -------------------------------------------------------------------------------- /src/FluentIL/IEventBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | 6 | /// 7 | /// Defines the event builder interface. 8 | /// 9 | public interface IEventBuilder 10 | { 11 | /// 12 | /// Gets the events attributes. 13 | /// 14 | EventAttributes EventAttributes { get; } 15 | 16 | /// 17 | /// Adds the 'SpecialName' attribute. 18 | /// 19 | /// The instance. 20 | IEventBuilder SpecialName(); 21 | 22 | /// 23 | /// Adds the 'RTSpecialName' attribute. 24 | /// 25 | /// The instance. 26 | IEventBuilder RTSpecialName(); 27 | 28 | /// 29 | /// Defines the . 30 | /// 31 | /// An instance. 32 | EventBuilder Define(); 33 | } 34 | } -------------------------------------------------------------------------------- /src/FluentIL/IFieldBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// Defines the field builder interface. 9 | /// 10 | public interface IFieldBuilder 11 | { 12 | /// 13 | /// Gets the fields name. 14 | /// 15 | string FieldName { get; } 16 | 17 | /// 18 | /// Gets the fields type. 19 | /// 20 | Type FieldType { get; } 21 | 22 | /// 23 | /// Gets or sets the field attributes. 24 | /// 25 | FieldAttributes FieldAttributes { get; set; } 26 | 27 | /// 28 | /// Sets the fields attributes. 29 | /// 30 | /// The field attributes. 31 | /// A . 32 | IFieldBuilder Attributes(FieldAttributes attributes); 33 | 34 | /// 35 | /// Defines the field builder. 36 | /// 37 | /// A . 38 | FieldBuilder Define(); 39 | } 40 | } -------------------------------------------------------------------------------- /src/FluentIL/IGenericParameterBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// Defines the generic parameter builder interface. 9 | /// 10 | public interface IGenericParameterBuilder 11 | { 12 | /// 13 | /// Gets or sets the generic parameters attributes. 14 | /// 15 | GenericParameterAttributes Attributes { get; set; } 16 | 17 | /// 18 | /// Gets the generic parameters name. 19 | /// 20 | string ParameterName { get; } 21 | 22 | /// 23 | /// Sets the base type that a type must inherit in order to be substituted for the type parameter. 24 | /// 25 | /// The base type. 26 | /// The instance. 27 | IGenericParameterBuilder BaseType(); 28 | 29 | /// 30 | /// Sets the base type that a type must inherit in order to be substituted for the type parameter. 31 | /// 32 | /// The base type. 33 | /// The instance. 34 | IGenericParameterBuilder BaseType(Type baseType); 35 | 36 | /// 37 | /// Sets the interfaces a type must implement in order to be substituted for the type parameter. 38 | /// 39 | /// The interface type. 40 | /// The instance. 41 | IGenericParameterBuilder InterfaceType(); 42 | 43 | /// 44 | /// Sets the interfaces a type must implement in order to be substituted for the type parameter. 45 | /// 46 | /// The interface type. 47 | /// The instance. 48 | IGenericParameterBuilder InterfaceType(Type interfaceType); 49 | 50 | /// 51 | /// The generic type parameter is covariant. A covariant type parameter can appear as the result 52 | /// type of a method, the type of a read-only field, a declared base type, or an implemented interface. 53 | /// 54 | /// The instance. 55 | IGenericParameterBuilder Covariant(); 56 | 57 | /// 58 | /// The generic type parameter is contravariant. A contravariant type parameter can appear as a parameter 59 | /// type in method signatures. 60 | /// 61 | /// The instance. 62 | IGenericParameterBuilder Contravariant(); 63 | 64 | /// 65 | /// A type can be substituted for the generic type parameter only if it has a parameterless constructor. 66 | /// 67 | /// The instance. 68 | IGenericParameterBuilder DefaultConstructor(); 69 | 70 | /// 71 | /// A type can be substituted for the generic type parameter only if it is a value type and is not nullable. 72 | /// 73 | /// The instance. 74 | IGenericParameterBuilder NotNullableValueType(); 75 | 76 | /// 77 | /// A type can be substituted for the generic type parameter only if it is a reference type. 78 | /// 79 | /// The instance. 80 | IGenericParameterBuilder ReferenceType(); 81 | 82 | /// 83 | /// Defines the generic parameter. 84 | /// 85 | /// The instance. 86 | Type AsType(); 87 | } 88 | } -------------------------------------------------------------------------------- /src/FluentIL/ILabel.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | /// 4 | /// Defines the label interface. 5 | /// 6 | public interface ILabel 7 | { 8 | /// 9 | /// Gets or sets the name of the label. 10 | /// 11 | string Name { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/FluentIL/ILocal.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | 5 | /// 6 | /// Defines the local variable interface. 7 | /// 8 | public interface ILocal 9 | { 10 | /// 11 | /// Gets the name of the local. 12 | /// 13 | string Name { get; } 14 | 15 | /// 16 | /// Gets a value indicating whether ot not the local is pinned. 17 | /// 18 | bool IsPinned { get; } 19 | 20 | /// 21 | /// Gets the locals index. 22 | /// 23 | int LocalIndex { get; } 24 | 25 | /// 26 | /// Gets the locals type. 27 | /// 28 | Type LocalType { get; } 29 | } 30 | } -------------------------------------------------------------------------------- /src/FluentIL/IModuleBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System.Reflection; 4 | 5 | /// 6 | /// Defines a module builder. 7 | /// 8 | public interface IModuleBuilder 9 | { 10 | /// 11 | /// Defines a type. 12 | /// 13 | /// The name of the type. 14 | /// A instance. 15 | ITypeBuilder NewType(string typeName); 16 | 17 | /// 18 | /// Defines a global method. 19 | /// 20 | /// The name of the method. 21 | /// A instance. 22 | IMethodBuilder NewGlobalMethod(string methodName); 23 | 24 | /// 25 | /// Creates any global methods defined in the module. 26 | /// 27 | /// A instance. 28 | IModuleBuilder CreateGlobalFunctions(); 29 | 30 | /// 31 | /// Gets a global method defined on the module. 32 | /// 33 | /// The name of the method. 34 | /// A instance if found; otherwise null. 35 | MethodInfo GetMethod(string methodName); 36 | } 37 | } -------------------------------------------------------------------------------- /src/FluentIL/IParameterBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Reflection.Emit; 5 | 6 | /// 7 | /// Defines the parameter builder interface. 8 | /// 9 | public interface IParameterBuilder 10 | { 11 | /// 12 | /// Specifies the parameters type. 13 | /// 14 | /// The parameter type. 15 | /// The instance. 16 | IParameterBuilder Type(); 17 | 18 | /// 19 | /// Specifies the parameters type. 20 | /// 21 | /// The parameters type. 22 | /// The instance. 23 | IParameterBuilder Type(Type parameterType); 24 | 25 | /// 26 | /// Specifies the parameters name. 27 | /// 28 | /// The parameters name. 29 | /// The instance. 30 | IParameterBuilder Name(string parameterName); 31 | 32 | /// 33 | /// Specifies that the parameter is an input parameter. 34 | /// 35 | /// The instance. 36 | IParameterBuilder In(); 37 | 38 | /// 39 | /// Specifies that the parameter is an output parameter. 40 | /// 41 | /// The instance. 42 | IParameterBuilder Out(); 43 | 44 | /// 45 | /// Specifies that the parameter is a locale identifier (lcid). 46 | /// 47 | /// The instance. 48 | IParameterBuilder Lcid(); 49 | 50 | /// 51 | /// Specifies that the parameter is a return value. 52 | /// 53 | /// The instance. 54 | IParameterBuilder Retval(); 55 | 56 | /// 57 | /// Specifies that the parameter is optional. 58 | /// 59 | /// The instance. 60 | IParameterBuilder Optional(); 61 | 62 | /// 63 | /// Specifies that the parameter has a default value. 64 | /// 65 | /// The instance. 66 | IParameterBuilder HasDefault(); 67 | 68 | /// 69 | /// Specifies that the parameter has field marshaling information. 70 | /// 71 | /// The instance. 72 | IParameterBuilder HasFieldMarshal(); 73 | 74 | /// 75 | /// Sets a custom attribute. 76 | /// 77 | /// The custom attribute. 78 | /// The instance. 79 | IParameterBuilder SetCustomAttribute(CustomAttributeBuilder attributeBuilder); 80 | } 81 | } -------------------------------------------------------------------------------- /src/FluentIL/IPropertyBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | /// 8 | /// Defines the property builder interface. 9 | /// 10 | public interface IPropertyBuilder 11 | { 12 | /// 13 | /// Gets or sets the property attributes. 14 | /// 15 | PropertyAttributes PropertyAttributes { get; set; } 16 | 17 | /// 18 | /// Gets or sets the set method. 19 | /// 20 | IMethodBuilder SetMethod { get; set; } 21 | 22 | /// 23 | /// Gets or sets the get method. 24 | /// 25 | IMethodBuilder GetMethod { get; set; } 26 | 27 | /// 28 | /// Sets the calling convention. 29 | /// 30 | /// The calling convention. 31 | /// The instance. 32 | IPropertyBuilder CallingConvention(CallingConventions callingConvention); 33 | 34 | /// 35 | /// Sets the attributes for the property. 36 | /// 37 | /// The attributes to set. 38 | /// The instance. 39 | IPropertyBuilder Attributes(PropertyAttributes attributes); 40 | 41 | /// 42 | /// Gets or adds the property get method builder. 43 | /// 44 | /// A method builder action. 45 | /// The instance. 46 | IPropertyBuilder Getter(Action action = null); 47 | 48 | /// 49 | /// Gets or adds the property get method builder. 50 | /// 51 | /// The get methods instance. 52 | IMethodBuilder Getter(); 53 | 54 | /// 55 | /// Gets or adds the property set method builder. 56 | /// 57 | /// A method builder action. 58 | /// The instance. 59 | IPropertyBuilder Setter(Action action = null); 60 | 61 | /// 62 | /// Gets or adds the property set method builder. 63 | /// 64 | /// The set methods instance. 65 | IMethodBuilder Setter(); 66 | 67 | /// 68 | /// Defines the property. 69 | /// 70 | /// A . 71 | PropertyBuilder Define(); 72 | } 73 | } -------------------------------------------------------------------------------- /src/FluentIL/TypeFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Reflection.Emit; 7 | 8 | /// 9 | /// Represents a type factory. 10 | /// 11 | public class TypeFactory 12 | { 13 | /// 14 | /// The default instance. 15 | /// 16 | private static Lazy instance = new Lazy(() => new TypeFactory("Default", "Default"), true); 17 | 18 | /// 19 | /// The assemlby cache. 20 | /// 21 | private AssemblyBuilderCache assemblyCache; 22 | 23 | /// 24 | /// The assembly builder. 25 | /// 26 | private IAssemblyBuilder assemblyBuilder; 27 | 28 | /// 29 | /// THe module builder. 30 | /// 31 | private IModuleBuilder moduleBuilder; 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// 36 | /// The assembly name. 37 | /// The module name. 38 | public TypeFactory(string assemblyName, string moduleName) 39 | { 40 | Utility.ThrowIfArgumentNullEmptyOrWhitespace(assemblyName, nameof(assemblyName)); 41 | Utility.ThrowIfArgumentNullEmptyOrWhitespace(moduleName, nameof(moduleName)); 42 | 43 | this.assemblyCache = new AssemblyBuilderCache(); 44 | this.assemblyBuilder = this.assemblyCache.GetOrCreateAssemblyBuilder(assemblyName); 45 | this.moduleBuilder = this.assemblyBuilder.NewDynamicModule(moduleName); 46 | } 47 | 48 | /// 49 | /// Gets the default type factory. 50 | /// 51 | public static TypeFactory Default 52 | { 53 | get 54 | { 55 | return instance.Value; 56 | } 57 | } 58 | 59 | /// 60 | /// Defines a anonymous type. 61 | /// 62 | /// A type builder. 63 | public ITypeBuilder NewType() 64 | { 65 | return this.NewType(Guid.NewGuid().ToString()); 66 | } 67 | 68 | /// 69 | /// Defines a named type. 70 | /// 71 | /// The name of the type. 72 | /// A type builder. 73 | public ITypeBuilder NewType(string typeName) 74 | { 75 | return this.moduleBuilder.NewType(typeName); 76 | } 77 | 78 | /// 79 | /// Defines a named delegate type. 80 | /// 81 | /// The return type. 82 | /// The name of the delegate type. 83 | /// The parameter types. 84 | /// The delegate type. 85 | public Type NewDelegateType(string typeName, Type[] parameterTypes) 86 | { 87 | return this.NewDelegateType(typeName, parameterTypes, typeof(TReturn)); 88 | } 89 | 90 | /// 91 | /// Defines a named delegate type. 92 | /// 93 | /// The name of the delegate type. 94 | /// The parameter types. 95 | /// The return type. 96 | /// The delegate type. 97 | public Type NewDelegateType(string typeName, Type[] parameterTypes, Type returnType) 98 | { 99 | var typeBuilder = this.moduleBuilder 100 | .NewType(typeName) 101 | .Attributes(TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass) 102 | .InheritsFrom(); 103 | 104 | typeBuilder.NewConstructor() 105 | .RTSpecialName() 106 | .HideBySig() 107 | .Public() 108 | .CallingConvention(CallingConventions.Standard) 109 | .Param("object") 110 | .Param("method") 111 | .SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed); 112 | 113 | typeBuilder.NewMethod("Invoke") 114 | .Public() 115 | .HideBySig() 116 | .NewSlot() 117 | .Virtual() 118 | .Returns(returnType) 119 | .Params(parameterTypes) 120 | .SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed); 121 | 122 | return typeBuilder.CreateType(); 123 | } 124 | 125 | /// 126 | /// Defines a global method. 127 | /// 128 | /// The method name. 129 | /// A instance. 130 | public IMethodBuilder NewGlobalMethod(string methodName) 131 | { 132 | return this.moduleBuilder.NewGlobalMethod(methodName); 133 | } 134 | 135 | /// 136 | /// Creates the global functions in a module. 137 | /// 138 | public void CreateGlobalFunctions() 139 | { 140 | this.moduleBuilder.CreateGlobalFunctions(); 141 | } 142 | 143 | /// 144 | /// Gets a method from the type factory. 145 | /// 146 | /// The method name. 147 | /// A instance if found; otherwise null. 148 | public MethodInfo GetMethod(string methodName) 149 | { 150 | return this.moduleBuilder.GetMethod(methodName); 151 | } 152 | 153 | /// 154 | /// Gets a type by name. 155 | /// 156 | /// The name of the type. 157 | /// Optional value indicating whether only dynamic assemblies should be checked or not. 158 | /// A representing the type if found; otherwise null. 159 | public Type GetType(string typeName, bool dynamicOnly = false) 160 | { 161 | var list = this.assemblyCache.GetAssemblies() 162 | .Union(AssemblyCache.GetAssemblies(dynamicOnly)); 163 | 164 | foreach (var ass in list) 165 | { 166 | Type type = ass.GetType(typeName); 167 | if (type != null) 168 | { 169 | return type; 170 | } 171 | } 172 | 173 | return null; 174 | } 175 | } 176 | } -------------------------------------------------------------------------------- /src/FluentIL/Utility.cs: -------------------------------------------------------------------------------- 1 | namespace FluentIL 2 | { 3 | using System; 4 | 5 | /// 6 | /// Various utility methods. 7 | /// 8 | internal static class Utility 9 | { 10 | /// 11 | /// Throws an exception if the passed argument is null. 12 | /// 13 | /// The arguement. 14 | /// The argument name. 15 | public static void ThrowIfArgumentNull(object argument, string argumentName) 16 | { 17 | if (argument == null) 18 | { 19 | throw new ArgumentNullException(argumentName); 20 | } 21 | } 22 | 23 | /// 24 | /// Throws an exception if the passed argument is null or empty. 25 | /// 26 | /// The arguement. 27 | /// The argument name. 28 | public static void ThrowIfArgumentNullOrEmpty(string argument, string argumentName) 29 | { 30 | Utility.ThrowIfArgumentNull(argument, argumentName); 31 | 32 | if (argument == string.Empty) 33 | { 34 | throw new ArgumentException("Argument is empty", argumentName); 35 | } 36 | } 37 | 38 | /// 39 | /// Throws an exception if the passed argument is null, empty or contains whitespace. 40 | /// 41 | /// The arguement. 42 | /// The argument name. 43 | public static void ThrowIfArgumentNullEmptyOrWhitespace(string argument, string argumentName) 44 | { 45 | Utility.ThrowIfArgumentNullOrEmpty(argument, argumentName); 46 | 47 | if (argument.IndexOf(' ') != -1) 48 | { 49 | throw new ArgumentException("Argument contains whitespace", argumentName); 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 3 | "settings": { 4 | "documentationRules": { 5 | "documentPrivateElements": true, 6 | "documentPrivateFields": true 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /test/FluentILExamples/FluentILExamples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | ../../ca.ruleset 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/FluentILUnitTests/BoxUnBoxUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using System.Reflection.Emit; 5 | using FluentIL; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | /// 9 | /// Box Unbox Unit Tests. 10 | /// 11 | [TestClass] 12 | public class BoxUnboxUnitTests 13 | { 14 | /// 15 | /// Box Value Type. 16 | /// 17 | [TestMethod] 18 | public void BoxValueType() 19 | { 20 | var typeBuilder = TypeFactory 21 | .Default 22 | .NewType("BoxTest") 23 | .Public(); 24 | 25 | typeBuilder 26 | .NewMethod("IntToString") 27 | .Public() 28 | .Param() 29 | .Returns() 30 | .Body() 31 | .LdArg1() 32 | .Box(typeof(int)) 33 | .CallVirt(typeof(object).GetMethod("ToString")) 34 | .Ret(); 35 | 36 | var type = typeBuilder.CreateType(); 37 | var obj = Activator.CreateInstance(type); 38 | var intToString = type.GetMethod("IntToString", new[] { typeof(int) }); 39 | 40 | var value = intToString.Invoke(obj, new object[] { 10 }); 41 | Assert.AreEqual("10", value); 42 | } 43 | 44 | /// 45 | /// Unbox Value Type. 46 | /// 47 | [TestMethod] 48 | public void UnboxValueType() 49 | { 50 | var typeBuilder = TypeFactory 51 | .Default 52 | .NewType("UnboxTest") 53 | .Public(); 54 | 55 | typeBuilder 56 | .NewMethod("ObjectToInt") 57 | .Public() 58 | .Param() 59 | .Returns() 60 | .Body() 61 | .DeclareLocal(out ILocal intValue) 62 | .LdArg1() 63 | .Unbox(typeof(int)) 64 | .LdIndI4() 65 | .Ret(); 66 | 67 | var type = typeBuilder.CreateType(); 68 | var obj = Activator.CreateInstance(type); 69 | var objectToInt = type.GetMethod("ObjectToInt", new[] { typeof(object) }); 70 | 71 | var boxedInt = (object)10; 72 | var value = objectToInt.Invoke(obj, new object[] { boxedInt }); 73 | Assert.AreEqual(10, value); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/ConstructorUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using System.Reflection; 5 | using FluentIL; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | /// 9 | /// Constructor Unit Tests. 10 | /// 11 | [TestClass] 12 | public class ConstructorUnitTests 13 | { 14 | /// 15 | /// New Constructor. 16 | /// 17 | [TestMethod] 18 | public void NewConstructor() 19 | { 20 | var typeBuilder = TypeFactory 21 | .Default 22 | .NewType(Guid.NewGuid().ToString()) 23 | .Public(); 24 | 25 | typeBuilder 26 | .NewConstructor() 27 | .Public() 28 | .Body() 29 | .Ret(); 30 | 31 | var type = typeBuilder.CreateType(); 32 | var obj = Activator.CreateInstance(type); 33 | 34 | Assert.IsNotNull(obj); 35 | } 36 | 37 | /// 38 | /// New Default Constructor. 39 | /// 40 | [TestMethod] 41 | public void NewDefaultConstructor() 42 | { 43 | var typeBuilder = TypeFactory 44 | .Default 45 | .NewType(Guid.NewGuid().ToString()) 46 | .Public(); 47 | 48 | typeBuilder 49 | .NewDefaultConstructor(MethodAttributes.Public); 50 | 51 | var type = typeBuilder.CreateType(); 52 | var obj = Activator.CreateInstance(type); 53 | 54 | Assert.IsNotNull(obj); 55 | } 56 | 57 | /// 58 | /// New Constructor with one argument. 59 | /// 60 | [TestMethod] 61 | public void NewConstructor_WithOneArgument() 62 | { 63 | var typeBuilder = TypeFactory 64 | .Default 65 | .NewType(Guid.NewGuid().ToString()) 66 | .Public(); 67 | 68 | typeBuilder 69 | .NewConstructor() 70 | .Public() 71 | .Param("arg1") 72 | .Body() 73 | .Ret(); 74 | 75 | var type = typeBuilder.CreateType(); 76 | var obj = Activator.CreateInstance(type, new object[] { 10 }); 77 | 78 | Assert.IsNotNull(obj); 79 | } 80 | 81 | /// 82 | /// New Constructor with one argument. 83 | /// 84 | [TestMethod] 85 | public void NewConstructor_WithTwoArguments() 86 | { 87 | var typeBuilder = TypeFactory 88 | .Default 89 | .NewType(Guid.NewGuid().ToString()) 90 | .Public(); 91 | 92 | typeBuilder 93 | .NewConstructor() 94 | .Public() 95 | .Param("arg1") 96 | .Param("arg2") 97 | .Body() 98 | .Ret(); 99 | 100 | var type = typeBuilder.CreateType(); 101 | var obj = Activator.CreateInstance(type, new object[] { 10, "Test" }); 102 | 103 | Assert.IsNotNull(obj); 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/DynamicMethodUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using FluentIL; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | /// 7 | /// Dynamic Method Unit Tests. 8 | /// 9 | [TestClass] 10 | public class DynamicMethodUnitTests 11 | { 12 | /// 13 | /// Test. 14 | /// 15 | [TestMethod] 16 | public void Test() 17 | { 18 | var addTwoIntegers = DynamicMethodFactory.Default 19 | .NewDynamicMethod("AddTwoIntegers", typeof(DynamicMethodUnitTests)) 20 | .Param("arg1") 21 | .Param("arg2") 22 | .Returns() 23 | .Body(m => m 24 | .LdArg0() 25 | .LdArg1() 26 | .Add() 27 | .Ret()) 28 | .CreateFunc(); 29 | 30 | Assert.AreEqual(2, addTwoIntegers(1, 1)); 31 | Assert.AreEqual(4, addTwoIntegers(2, 2)); 32 | Assert.AreEqual(7, addTwoIntegers(3, 4)); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/EmitForEachUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using FluentIL; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | /// 9 | /// Emit For Each Unit Tests. 10 | /// 11 | [TestClass] 12 | public class EmitForEachUnitTests 13 | { 14 | /// 15 | /// Create Method With For Each. 16 | /// 17 | [TestMethod] 18 | public void CreateMethod_WithForEach() 19 | { 20 | var addItem = typeof(List) 21 | .BuildMethodInfo("Add") 22 | .HasParameterTypes(typeof(string)) 23 | .FirstOrDefault(); 24 | 25 | var testTypeBuilder = TypeFactory 26 | .Default 27 | .NewType($"TestType_{Guid.NewGuid()}"); 28 | 29 | testTypeBuilder 30 | .NewMethod("TestMethod") 31 | .Public() 32 | .Param>("source") 33 | .Param>("list") 34 | .Body() 35 | .DeclareLocal>(out ILocal localSource) 36 | .DeclareLocal>(out ILocal localList) 37 | .LdArg1() 38 | .StLoc(localSource) 39 | .LdArg2() 40 | .StLoc(localList) 41 | .Nop() 42 | .ForEach( 43 | localSource, 44 | (il, item) => 45 | { 46 | il 47 | .LdLoc(localList) 48 | .LdLoc(item) 49 | .CallVirt(addItem); 50 | }) 51 | .Ret(); 52 | 53 | var testType = testTypeBuilder.CreateType(); 54 | var testMethod = testType.GetMethod("TestMethod"); 55 | 56 | var list = new List(); 57 | var source = new[] { "A", "B", "C" }; 58 | 59 | var obj = Activator.CreateInstance(testType); 60 | testMethod.Invoke(obj, new object[] { source, list }); 61 | 62 | Assert.AreEqual(source.Length, list.Count); 63 | for (int i = 0; i < source.Length; i++) 64 | { 65 | Assert.AreEqual(source[i], list[i]); 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/EmitForUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using FluentIL; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | /// 9 | /// Emit For Unit Tests. 10 | /// 11 | [TestClass] 12 | public class EmitForUnitTests 13 | { 14 | /// 15 | /// Create Method With Index For Loop. 16 | /// 17 | [TestMethod] 18 | public void CreateMethod_WithIndexForLoop() 19 | { 20 | var addItem = typeof(List) 21 | .BuildMethodInfo("Add") 22 | .HasParameterTypes(typeof(string)) 23 | .FirstOrDefault(); 24 | 25 | var testTypeBuilder = TypeFactory 26 | .Default 27 | .NewType($"TestType_{Guid.NewGuid()}"); 28 | 29 | testTypeBuilder 30 | .NewMethod("TestMethod") 31 | .Public() 32 | .Param("source") 33 | .Param>("list") 34 | .Body() 35 | .DeclareLocal(out ILocal localArray) 36 | .DeclareLocal>(out ILocal localList) 37 | .DeclareLocal("length", out ILocal length) 38 | 39 | .LdArg1() 40 | .StLoc(localArray) 41 | .LdArg2() 42 | .StLoc(localList) 43 | .Nop() 44 | .LdLoc(localArray) 45 | .LdLen() 46 | .StLoc(length) 47 | .Nop() 48 | .For( 49 | length, 50 | (il, index) => 51 | { 52 | il 53 | .LdLoc(localList) 54 | .LdLoc(localArray) 55 | .LdLoc(index) 56 | .LdElemRef() 57 | .CallVirt(addItem); 58 | }) 59 | .Ret(); 60 | 61 | var testType = testTypeBuilder.CreateType(); 62 | var testMethod = testType.GetMethod("TestMethod"); 63 | 64 | var list = new List(); 65 | var source = new[] { "A", "B", "C" }; 66 | 67 | var obj = Activator.CreateInstance(testType); 68 | testMethod.Invoke(obj, new object[] { source, list }); 69 | 70 | Assert.AreEqual(source.Length, list.Count); 71 | for (int i = 0; i < source.Length; i++) 72 | { 73 | Assert.AreEqual(source[i], list[i]); 74 | } 75 | } 76 | 77 | /// 78 | /// Create Method With Index And Array For Loop. 79 | /// 80 | [TestMethod] 81 | public void CreateMethod_WithIndexAndArrayForLoop() 82 | { 83 | var addItem = typeof(List) 84 | .BuildMethodInfo("Add") 85 | .HasParameterTypes(typeof(string)) 86 | .FirstOrDefault(); 87 | 88 | var testTypeBuilder = TypeFactory 89 | .Default 90 | .NewType($"TestType_{Guid.NewGuid()}"); 91 | 92 | testTypeBuilder 93 | .NewMethod("TestMethod") 94 | .Public() 95 | .Param("source") 96 | .Param>("list") 97 | .Body() 98 | .DeclareLocal(out ILocal localArray) 99 | .DeclareLocal>(out ILocal localList) 100 | 101 | .LdArg1() 102 | .StLoc(localArray) 103 | .LdArg2() 104 | .StLoc(localList) 105 | .Nop() 106 | .For( 107 | localArray, 108 | (il, index, item) => 109 | { 110 | il 111 | .LdLoc(localList) 112 | .LdLoc(item) 113 | .CallVirt(addItem); 114 | }) 115 | .Ret(); 116 | 117 | var testType = testTypeBuilder.CreateType(); 118 | var testMethod = testType.GetMethod("TestMethod"); 119 | 120 | var list = new List(); 121 | var source = new[] { "A", "B", "C" }; 122 | 123 | var obj = Activator.CreateInstance(testType); 124 | testMethod.Invoke(obj, new object[] { source, list }); 125 | 126 | Assert.AreEqual(source.Length, list.Count); 127 | for (int i = 0; i < source.Length; i++) 128 | { 129 | Assert.AreEqual(source[i], list[i]); 130 | } 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/FluentILUnitTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1;net5.0 5 | false 6 | ../../ca.ruleset 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/FluentILUnitTests/GenericTypeUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using FluentIL; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | /// 8 | /// Generic Type Unit Tests. 9 | /// 10 | [TestClass] 11 | public class GenericTypeUnitTests 12 | { 13 | /// 14 | /// Create Simple Generic Type. 15 | /// 16 | [TestMethod] 17 | public void CreateSimpleGenericType() 18 | { 19 | ////DebugOutput.Output = new ConsoleOutput(); 20 | 21 | var testTypeBuilder = TypeFactory 22 | .Default 23 | .NewType($"TestType_{Guid.NewGuid()}") 24 | .NewGenericParameter("T", null) 25 | .Public(); 26 | 27 | var typeT = testTypeBuilder.GetGenericParameterType("T"); 28 | 29 | var field = testTypeBuilder 30 | .NewField("property", typeT); 31 | 32 | testTypeBuilder 33 | .NewMethod("SetValue") 34 | .Public() 35 | .Param(typeT, "value") 36 | .Body(il => il 37 | .LdArg0() 38 | .LdArg1() 39 | .StFld(field) 40 | .Ret()); 41 | 42 | testTypeBuilder 43 | .NewProperty("Value", typeT) 44 | .Getter(m => m 45 | .Public() 46 | .Body(il => il 47 | .LdArg0() 48 | .LdFld(field) 49 | .Ret())); 50 | 51 | var testType = testTypeBuilder.CreateType(); 52 | Assert.IsNotNull(testType); 53 | 54 | var genericTestType = testType.MakeGenericType(typeof(string)); 55 | Assert.IsNotNull(genericTestType); 56 | 57 | var instance = Activator.CreateInstance(genericTestType); 58 | Assert.IsNotNull(instance); 59 | 60 | genericTestType.GetMethod("SetValue").Invoke(instance, new object[] { "Test" }); 61 | var result = genericTestType.GetProperty("Value").GetGetMethod().Invoke(instance, null); 62 | Assert.AreEqual("Test", result as string); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/ModuleMethodUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | using FluentIL; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | /// 10 | /// Module Method Unit Tests. 11 | /// 12 | [TestClass] 13 | public class ModuleMethodUnitTests 14 | { 15 | /// 16 | /// Create Global Method With Parameters And Return. 17 | /// 18 | [TestMethod] 19 | public void CreateGlobalMethod_WithParametersAndReturn() 20 | { 21 | var addMethodBuilder = TypeFactory 22 | .Default 23 | .NewGlobalMethod("Add") 24 | .Public() 25 | .Static() 26 | .Param("first") 27 | .Param("second") 28 | .Returns() 29 | .Body(il => il 30 | .LdArg0() 31 | .LdArg1() 32 | .Add() 33 | .Ret()); 34 | 35 | addMethodBuilder.Define(); 36 | 37 | TypeFactory 38 | .Default 39 | .CreateGlobalFunctions(); 40 | 41 | var methodInfo = TypeFactory 42 | .Default 43 | .GetMethod("Add"); 44 | 45 | var method = (Func)methodInfo.CreateDelegate(typeof(Func)); 46 | var result = method(10, 20); 47 | 48 | Assert.AreEqual(30, (int)result); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/ParameterBuilderUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using FluentIL; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | /// 8 | /// Parameter Builder Unit Tests. 9 | /// 10 | [TestClass] 11 | public class ParameterBuilderUnitTests 12 | { 13 | /// 14 | /// Create Method With Parameters Using Params. 15 | /// 16 | [TestMethod] 17 | public void CreateMethod_WithParametersUsingParams() 18 | { 19 | const string Format = "arg1 = {0}, arg2 = {1}"; 20 | 21 | var formatMethodInfo = typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object), typeof(object) }); 22 | 23 | var typeBuilder = TypeFactory 24 | .Default 25 | .NewType(Guid.NewGuid().ToString()) 26 | .Public(); 27 | 28 | var methodBuilder = typeBuilder 29 | .NewMethod("TestMethod") 30 | .Param("arg1") 31 | .Param("arg2") 32 | .Returns() 33 | .Public() 34 | .Body(e => e 35 | .LdStr(Format) 36 | .LdArg1() 37 | .LdArg2() 38 | .Box() 39 | .Call(formatMethodInfo) 40 | .Ret()); 41 | 42 | var type = typeBuilder.CreateType(); 43 | var instance = Activator.CreateInstance(type); 44 | var method = instance.GetMethodFunc("TestMethod"); 45 | 46 | var arg1 = "Hello"; 47 | var arg2 = 100; 48 | 49 | Assert.AreEqual(string.Format(Format, arg1, arg2), method(arg1, arg2)); 50 | } 51 | 52 | /// 53 | /// Create Method With Parameters Using Parameter Builders. 54 | /// 55 | [TestMethod] 56 | public void CreateMethod_WithParametersUsingParameterBuilders() 57 | { 58 | const string Format = "arg1 = {0}, arg2 = {1}"; 59 | 60 | var formatMethodInfo = typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object), typeof(object) }); 61 | 62 | var typeBuilder = TypeFactory 63 | .Default 64 | .NewType(Guid.NewGuid().ToString()) 65 | .Public(); 66 | 67 | var methodBuilder = typeBuilder 68 | .NewMethod("TestMethod") 69 | .Returns() 70 | .Public(); 71 | 72 | var arg1Parm = methodBuilder.CreateParam("arg1"); 73 | var arg2Parm = methodBuilder.CreateParam("arg2"); 74 | 75 | methodBuilder 76 | .Params(arg1Parm, arg2Parm) 77 | .Body(e => e 78 | .LdStr(Format) 79 | .LdArg1() 80 | .LdArg2() 81 | .Box() 82 | .Call(formatMethodInfo) 83 | .Ret()); 84 | 85 | var type = typeBuilder.CreateType(); 86 | var instance = Activator.CreateInstance(type); 87 | var method = instance.GetMethodFunc("TestMethod"); 88 | 89 | var arg1 = "Hello"; 90 | var arg2 = 100; 91 | 92 | Assert.AreEqual(string.Format(Format, arg1, arg2), method(arg1, arg2)); 93 | } 94 | 95 | /// 96 | /// Create Method With Parameters Using Param Actions. 97 | /// 98 | [TestMethod] 99 | public void CreateMethod_WithParametersUsingParamActions() 100 | { 101 | const string Format = "arg1 = {0}, arg2 = {1}"; 102 | 103 | var formatMethodInfo = typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object), typeof(object) }); 104 | 105 | var typeBuilder = TypeFactory 106 | .Default 107 | .NewType(Guid.NewGuid().ToString()) 108 | .Public(); 109 | 110 | var methodBuilder = typeBuilder 111 | .NewMethod("TestMethod") 112 | .Param(p => p.Name("arg1").Type()) 113 | .Param(p => p.Name("arg2").Type()) 114 | .Returns() 115 | .Public() 116 | .Body(e => e 117 | .LdStr(Format) 118 | .LdArg1() 119 | .LdArg2() 120 | .Box() 121 | .Call(formatMethodInfo) 122 | .Ret()); 123 | 124 | var type = typeBuilder.CreateType(); 125 | var instance = Activator.CreateInstance(type); 126 | var method = instance.GetMethodFunc("TestMethod"); 127 | 128 | var arg1 = "Hello"; 129 | var arg2 = 100; 130 | 131 | Assert.AreEqual(string.Format(Format, arg1, arg2), method(arg1, arg2)); 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/Resources/ITestInterface.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests.Resources 2 | { 3 | /// 4 | /// defines a test interface. 5 | /// 6 | public interface ITestInterface 7 | { 8 | /// 9 | /// Gets or sets a property. 10 | /// 11 | string GetSetProperty { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/TypeFactoryUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using FluentIL; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | /// 8 | /// Type Factory Unit Tests. 9 | /// 10 | [TestClass] 11 | public class TypeFactoryUnitTests 12 | { 13 | /// 14 | /// Default Type Factory New Type Creates New Type. 15 | /// 16 | [TestMethod] 17 | public void DefaultTypeFactory_NewType_CreatesNewType() 18 | { 19 | var testTypeBuilder = TypeFactory 20 | .Default 21 | .NewType(); 22 | 23 | Assert.IsNotNull(testTypeBuilder); 24 | 25 | var testType = testTypeBuilder.CreateType(); 26 | 27 | Assert.IsNotNull(testType); 28 | 29 | var instance = Activator.CreateInstance(testType); 30 | 31 | Assert.IsNotNull(instance); 32 | } 33 | 34 | /// 35 | /// Type Factory New Type Creates New Type. 36 | /// 37 | [TestMethod] 38 | public void TypeFactory_NewType_CreatesNewType() 39 | { 40 | var typeFactory = new TypeFactory("TestAssembly", "TestModule"); 41 | var testTypeBuilder = typeFactory 42 | .NewType(); 43 | 44 | Assert.IsNotNull(testTypeBuilder); 45 | 46 | var testType = testTypeBuilder.CreateType(); 47 | 48 | Assert.IsNotNull(testType); 49 | 50 | var instance = Activator.CreateInstance(testType); 51 | 52 | Assert.IsNotNull(instance); 53 | } 54 | 55 | /// 56 | /// Create Type Factory With Null Assembly Name Throws. 57 | /// 58 | [TestMethod] 59 | [ExpectedException(typeof(ArgumentNullException))] 60 | public void CreateTypeFactory_WithNullAssemblyName_Throws() 61 | { 62 | new TypeFactory(null, "TestModule"); 63 | } 64 | 65 | /// 66 | /// Create Type Factory With Empty Assembly Name Throws. 67 | /// 68 | [TestMethod] 69 | [ExpectedException(typeof(ArgumentException))] 70 | public void CreateTypeFactory_WithEmptyAssemblyName_Throws() 71 | { 72 | new TypeFactory(string.Empty, "TestModule"); 73 | } 74 | 75 | /// 76 | /// Create Type Factory With Whitespace Assembly Name Throws. 77 | /// 78 | [TestMethod] 79 | [ExpectedException(typeof(ArgumentException))] 80 | public void CreateTypeFactory_WithWhitespaceAssemblyName_Throws() 81 | { 82 | new TypeFactory(" ", "TestModule"); 83 | } 84 | 85 | /// 86 | /// Create Type Factory With Null Module Name Throws. 87 | /// 88 | [TestMethod] 89 | [ExpectedException(typeof(ArgumentNullException))] 90 | public void CreateTypeFactory_WithNullModuleName_Throws() 91 | { 92 | new TypeFactory("TestAssembly", null); 93 | } 94 | 95 | /// 96 | /// Create Type Factory With Empty Module Name Throws. 97 | /// 98 | [TestMethod] 99 | [ExpectedException(typeof(ArgumentException))] 100 | public void CreateTypeFactory_WithEmptyModuleName_Throws() 101 | { 102 | new TypeFactory("TestAssembly", string.Empty); 103 | } 104 | 105 | /// 106 | /// Create Type Factory With Whitespace Module Name Throws. 107 | /// 108 | [TestMethod] 109 | [ExpectedException(typeof(ArgumentException))] 110 | public void CreateTypeFactory_WithWhitespaceModuleName_Throws() 111 | { 112 | new TypeFactory("TestAssembly", " "); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /test/FluentILUnitTests/TypeInterfaceUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using FluentIL; 5 | using FluentILUnitTests.Resources; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | /// 9 | /// Type Interface Unit Tests. 10 | /// 11 | [TestClass] 12 | public class TypeInterfaceUnitTests 13 | { 14 | /// 15 | /// Type Implement Interface. 16 | /// 17 | [TestMethod] 18 | public void Type_ImplementInterface() 19 | { 20 | var testTypeBuilder = TypeFactory 21 | .Default 22 | .NewType($"TestType_{Guid.NewGuid()}") 23 | .Public() 24 | .Implements(); 25 | 26 | var field = testTypeBuilder 27 | .NewField("property"); 28 | 29 | var property = testTypeBuilder 30 | .NewProperty("GetSetProperty") 31 | .Setter(m => m 32 | .Public() 33 | .Virtual() 34 | .Body(il => il 35 | .LdArg0() 36 | .LdArg1() 37 | .StFld(field) 38 | .Ret())) 39 | .Getter(m => m 40 | .Public() 41 | .Virtual() 42 | .Body(il => il 43 | .LdArg0() 44 | .LdFld(field) 45 | .Ret())); 46 | 47 | var testType = testTypeBuilder.CreateType(); 48 | Assert.IsNotNull(testType); 49 | 50 | var instance = Activator.CreateInstance(testType); 51 | Assert.IsNotNull(instance); 52 | 53 | ITestInterface testInterface = instance as ITestInterface; 54 | Assert.IsNotNull(testInterface); 55 | 56 | testInterface.GetSetProperty = "Test"; 57 | Assert.AreEqual("Test", testInterface.GetSetProperty); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/TypeMethodUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using System.Reflection; 5 | using FluentIL; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | /// 9 | /// Type Method Unit Tests. 10 | /// 11 | [TestClass] 12 | public class TypeMethodUnitTests 13 | { 14 | /// 15 | /// Create Method With Single String Parameter Returns Passed In String. 16 | /// 17 | [TestMethod] 18 | public void CreateMethod_WithSingleStringParameter_ReturnsPassedInString() 19 | { 20 | var testTypeBuilder = TypeFactory 21 | .Default 22 | .NewType($"TestType_{Guid.NewGuid()}"); 23 | 24 | var testMethodBuilder = testTypeBuilder 25 | .NewMethod("TestMethod") 26 | .Public() 27 | .Param("name"); 28 | 29 | testMethodBuilder 30 | .Body() 31 | .DeclareLocal(out ILocal local) 32 | .LdArg1() 33 | .StLoc(local) 34 | .Nop() 35 | .LdLoc(local) 36 | .Ret(); 37 | 38 | var testType = testTypeBuilder.CreateType(); 39 | 40 | var testMethod = testType.GetMethod("TestMethod"); 41 | Assert.IsNotNull(testMethod); 42 | 43 | var instance = Activator.CreateInstance(testType); 44 | Assert.IsNotNull(instance); 45 | 46 | var result = testMethod.Invoke(instance, new object[] { "Hello World" }); 47 | Assert.IsNotNull(result); 48 | Assert.AreEqual("Hello World", (string)result); 49 | } 50 | 51 | /// 52 | /// Create Method With Two String Parameters Returns Concatenated String. 53 | /// 54 | [TestMethod] 55 | public void CreateMethod_WithTwoStringParameters_ReturnsConcatenatedString() 56 | { 57 | var testTypeBuilder = TypeFactory 58 | .Default 59 | .NewType($"TestType_{Guid.NewGuid()}"); 60 | 61 | var testMethodBuilder = testTypeBuilder 62 | .NewMethod("TestMethod") 63 | .Public() 64 | .Param("first") 65 | .Param("second"); 66 | 67 | testMethodBuilder 68 | .Body() 69 | .DeclareLocal(out ILocal local) 70 | .LdArg1() 71 | .LdArg2() 72 | .Call(typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string) })) 73 | .StLoc(local) 74 | .Nop() 75 | .LdLoc(local) 76 | .Ret(); 77 | 78 | var testType = testTypeBuilder.CreateType(); 79 | 80 | var testMethod = testType.GetMethod("TestMethod"); 81 | Assert.IsNotNull(testMethod); 82 | 83 | var instance = Activator.CreateInstance(testType); 84 | Assert.IsNotNull(instance); 85 | 86 | var result = testMethod.Invoke(instance, new object[] { "Hello", "World" }); 87 | Assert.IsNotNull(result); 88 | Assert.AreEqual("HelloWorld", (string)result); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /test/FluentILUnitTests/TypePropertyUnitTests.cs: -------------------------------------------------------------------------------- 1 | namespace FluentILUnitTests 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Reflection; 6 | using FluentIL; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | /// 10 | /// Type Property Unit Tests. 11 | /// 12 | [TestClass] 13 | public class TypePropertyUnitTests 14 | { 15 | /// 16 | /// Create Property With String Field Get Value Matches Set Value. 17 | /// 18 | [TestMethod] 19 | public void CreateProperty_WithStringField_GetValueMatchesSetValue() 20 | { 21 | ////DebugOutput.Output = new ConsoleOutput(); 22 | 23 | var testTypeBuilder = TypeFactory 24 | .Default 25 | .NewType($"TestType_{Guid.NewGuid()}") 26 | .Public(); 27 | 28 | var fieldBuilder = testTypeBuilder 29 | .NewField("property") 30 | .Private(); 31 | 32 | var testPropertyBuilder = testTypeBuilder 33 | .NewProperty("Value"); 34 | 35 | testPropertyBuilder 36 | .Getter() 37 | .Public() 38 | .NewSlot() 39 | .Body() 40 | .LdArg0() 41 | .LdFld(fieldBuilder) 42 | .Ret(); 43 | 44 | testPropertyBuilder 45 | .Setter() 46 | .Public() 47 | .NewSlot() 48 | .Body() 49 | .LdArg0() 50 | .LdArg1() 51 | .StFld(fieldBuilder) 52 | .Ret(); 53 | 54 | var testType = testTypeBuilder.CreateType(); 55 | Assert.IsNotNull(testType); 56 | 57 | var testProperty = testType.GetProperty("Value"); 58 | Assert.IsNotNull(testProperty); 59 | 60 | var instance = Activator.CreateInstance(testType); 61 | Assert.IsNotNull(instance); 62 | 63 | testProperty.SetValue(instance, "Hello World"); 64 | 65 | var result = testProperty.GetValue(instance); 66 | 67 | Assert.AreEqual("Hello World", (string)result); 68 | } 69 | 70 | /// 71 | /// Set Property With Private Setter Using A Set Method. 72 | /// 73 | [TestMethod] 74 | public void SetPropertyWithPrivateSetter_UsingASetMethod() 75 | { 76 | var typeBuilder = TypeFactory 77 | .Default 78 | .NewType() 79 | .Public(); 80 | 81 | var field = typeBuilder 82 | .NewField("value") 83 | .Private(); 84 | 85 | var property = typeBuilder 86 | .NewProperty("Value") 87 | .Setter(m => m 88 | .Private() 89 | .Body() 90 | .LdArg0() 91 | .LdArg1() 92 | .StFld(field) 93 | .Ret()) 94 | .Getter(m => m 95 | .Public() 96 | .Body() 97 | .LdArg0() 98 | .LdFld(field) 99 | .Ret()); 100 | 101 | var setValue = typeBuilder 102 | .NewMethod("SetValue") 103 | .Public() 104 | .Param("value") 105 | .Body(m => m 106 | .LdArg0() 107 | .LdArg1() 108 | .Call(property.SetMethod) 109 | .Ret()); 110 | 111 | var type = typeBuilder.CreateType(); 112 | var obj = Activator.CreateInstance(type); 113 | 114 | type.GetMethod("SetValue").Invoke(obj, new object[] { "Test" }); 115 | var value = type.GetProperty("Value").GetValue(obj); 116 | 117 | Assert.AreEqual("Test", value); 118 | } 119 | } 120 | } --------------------------------------------------------------------------------