Reflection Emit Dynamic Method Scenarios
Dynamic methods created by using the DynamicMethod class (new in the .NET Framework version 2.0) provide enhanced capabilities for emitting static methods at run time. Dynamic methods expand the functionality of the types in the System.Reflection.Emit namespace in several ways:
They have less overhead, because there is no need to generate dynamic assemblies, modules, and types to contain the methods.
In long-running applications, they provide better resource utilization because the memory used by method bodies can be reclaimed when the method is no longer needed.
Given sufficient security permissions, they provide the ability to associate code with an existing assembly or type, and that code can have the same visibility as internal types or private members.
Given sufficient security permissions, they allow code to skip just-in-time (JIT) visibility checks and access the private and protected data of objects.
Dynamic methods can use an ILGenerator object to emit Microsoft intermediate language (MSIL). In addition, dynamic methods can use a DynamicILInfo object to work with metadata tokens and scopes that allow sophisticated clients to perform their own MSIL generation.
Dynamic methods are useful in scenarios where run-time code generation is required for performance. Examples discussed in this section include serialization, mappings between objects and relational databases, regular expressions, partial evaluation, and compilers for languages that require runtimes.
For a simple example of dynamic method generation, see How to: Define and Execute Dynamic Methods.
Languages That Support Late-Bound Calls
Dynamic methods are useful to compiler writers when the type of an object is not known at compile time. Calls to the object's members must be resolved at run time, frequently with the additional overhead of manipulating argument lists. The following Visual Basic code provides an example of this.
Sub Example(ByVal obj as Object) ' ... obj.SomeMethod(x, y, z) ' ... End Sub
The compiler must generate code to look up SomeMethod, prepare the arguments as an array of objects, and invoke the method. Executing such calls with reflection, using the InvokeMember method, does not provide good performance. Performance can be improved by using members of the System.Reflection.Emit namespace to create a dynamic assembly, module, type, and method, but this can result in a larger working set and greater code complexity. Dynamic methods allow a more efficient implementation strategy in cases where the dynamic method signature matches an existing delegate type, because there is no need to create a dynamic assembly, module, or type. This approach performs much better than using the InvokeMember method. It does not perform as well as a virtual call, but it requires a much smaller working set because no new types are created. Furthermore, the generated MSIL and associated native code can be reclaimed when no longer needed.
Dynamic methods can eliminate the need to write custom serialization and deserialization code. You can mark a serializable type according to simple rules and then use a serialization engine to examine the metadata for the type, generate an appropriate serializer and deserializer as needed, and run the generated code on instances of the type.
Given sufficient security permissions, a serialization engine implemented using dynamic methods can access private and protected data to enable serialization of objects not authored by the engine creator.
Generated methods can be cached if used frequently, or they can simply be released.
Partial evaluation, also known as program specialization, is a technique for optimizing algorithms where one or more of the input variables vary more slowly than the other inputs. Partial evaluation generates specialized method calls that treat the values of the slowly varying inputs as if they were constant, allowing additional optimizations to be applied to the algorithm as a whole.
Using this technique, it is often possible to transform a low-performance general-purpose algorithm into a high-performance specialized algorithm. The following are some examples:
Compiling a Regex object to generate a program that is specialized to match on a particular pattern.
Compiling a metadata-driven serialization engine into a program that is specialized to serialize and deserialize a specific type or set of types.
Compiling an XML schema to generate a program that is specialized to validate a particular schema.
Compiling an XSLT transformation into a program that is specialized to transform an XML document in a specific way.
Compiling a generic encryption program that encrypts data using any specified key into a program that is optimized for a particular key.
Dynamic methods can be used to implement partial evaluation by generating specialized methods at run time. In addition to performance improvements, dynamic methods allow reclamation of the MSIL method bodies and the related machine code produced by the JIT compiler. This can be critical in long-running programs.
For a description of some of these scenarios in more detail, see Reflection Emit Application Scenarios.
Generating Custom User Code at Run Time
Many applications or platforms have extensibility mechanisms that give users the ability to write and execute custom code while the application is running, frequently through the use of predefined functions. By using dynamic methods to generate this code, the application or platform designer can reduce the number of functions required (and hence the memory footprint) and provide more flexibility for the user without sacrificing performance.