⚠ Deprecated: Legacy
Suggested alternative: EmitToolbox
This framework provides a generator to generate proxy class which can override non-final virtual methods of base classes in run-time. The generator is implemented with dynamic IL weaving via System.Reflection.Emit library. It is designed in plugin model, which allows users to easily extend its function.
$ dotnet add package Pygmalions.Prism.FrameworkThis framework provides a generator to generate proxy class which can override non-final virtual methods of base classes in run-time.
The generator is implemented with dynamic IL weaving via System.Reflection.Emit library. It is designed in plugin model, which allows users to easily extend its function.
The proxy generator use Emit to generate dynamic class which is inherited from the class to proxy, so virtual methods will be override thus their behaviors can be modified.
A proxy generator is modular class generator based on static-IL-weaving with System.Reflection.Emit.
You write your own plugins to customize the generated proxy class, such as adding codes to proxied methods
and implementing more interfaces, etc.
A class context describe the class to proxy. It contains the dynamic class builder for the generator to use, and method contexts.
Class contexts are the basic unit for plugin to process. Plugins can do the most jobs with the dynamic class builder.
Initializer method is a special method which will be invoked by all constructors. Thus, you can write your initializing behavior in this method rather than every constructor.
Method contexts are used to shared method data among different plugins. Plugins can add code with delegates which will emit IL code with the ILGenerator. Those delegates will be invoked in sequence to generate the proxy method.
There are 3 stages of a method generation procedure:
The 2nd stage is the code which will invoke the proxied method directly. A code context has many properties or fields to control or describe this behavior, for example, the local variable which stores the return value of the proxied method.
Code contexts contains many fields or properties associated with the method code generation procedure.
You can use Skipped filed in the before-invoking stage to skip the invocation of the proxied method,
or to set the return value of the invocation of the generated method, or, passing values
between delegates in different stages with dictionary.
ResultDataResult field is a local variable builder which must be used in Emit context. The variable in it
will be overwrite by the 2nd stage (Invoking the proxied method), so you can access it in the 3rd stage,
or set a content to it and set Skipped true in the 1st stage (Before-invoking) to skip the proxied method,
which is the 2nd stage.
Attention, no matter the 2nd stage is skipped or not, the 3rd stage (After-invoking) will always be executed.
But codes in 3rd stage can access the Skipped to check whether the proxied method is skipped or not.
A plugin must implement IProxyPlugin interface and be marked with one or more TriggerBy attribute.
Then the Modify(ClassContext) method will be invoked if the proxied class triggers this plugin.
A plugin can be triggered in 3 ways:
A TriggerBy attribute can declare a trigger type for this plugin.
In ByAttribute mode, the plugin will be triggered by attributes which is assignable to the trigger type.
In ByHierarchy mode, the plugin will be triggered by proxied classes which is assignable to the trigger type.
We recommend your plugins to use interfaces as triggers, and you can provide some basic attribute classes implementing those interfaces. In this way, users can define a custom attribute to trigger multiple plugins.