You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Introduce a source generator to facilitate compile-time dynamic behavior injection. This generator will produce "plugin" implementations for classes or interfaces, allowing for behavior extension and customization without altering the original code.
Inspiration
This concept is inspired by the Strix Music SDK's "model plugin" system, which lets developers enhance the SDK by wrapping around and overriding SDK model members. Our goal is to generalize this idea for any class or interface.
Key Features
Plugin Generation: Automatically derive a "plugin" for any class or interface.
Delegation Mechanism: Utilize IDelegable<T> to delegate to other T instances when members aren't overridden.
Fallback Strategy: Non-overridden members default to IDelegable<T>.Inner.
Plugin Chaining: Chain multiple plugins, replacing the original object upon execution.
Interface Plugins: Apply interface plugins to any class inheriting the interface.
Generated Plugin Container: A container class that holds all the ChainedProxyBuilder instances for possible plugins.
Generated Wrapper Class: For each concrete class, a wrapper class is generated that applies the relevant plugins and delegates calls to the enhanced instance.
Workflow
Identify classes/interfaces marked for plugin generation.
Generate a derived "plugin" for each, implementing both T and IDelegable<T>.
The plugin accepts a T and an IDelegable<T> instance during construction.
Developers can extend the generated base class to craft custom plugins.
Non-overridden plugin members delegate to IDelegable<T>.Inner.
Use base or Inner to invoke the next plugin or the base class.
Generate a Plugin Container class that holds all the ChainedProxyBuilder instances for possible plugins.
Generate a Wrapper class for each concrete class that uses the Plugin Container to apply the relevant plugins and delegates calls to the enhanced instance.
Applications
RPC Library: Generate proxy implementations for interfaces, enabling a Remote Procedure Call library for distant method calls.
Dynamic Behavior: Craft plugins for behavior modification, logging, caching, validation, etc.
Modularity: Promote a modular design where core functionalities stem from base classes/interfaces, and plugins offer additional features.
Conclusion
This source generator promises a robust method to extend and customize class/interface behavior during compile-time. By crafting "plugin" implementations that can encapsulate and override originals, we're paving the way for a modular and scalable software architecture.
// Unsealed class, original implementation.publicclassMyClass:SomeBase,ISomething,ISomethingElse{publicvoidDoSomething(){}publicvoidMyMethod(){}}// Custom plugin derived from the generated plugin base class.// `Inner` may be the original implementation, a plugin, or a collapsed chain of plugins.publicpartialclassLoggingPlugin:SomethingPlugin{publicLoggingPlugin(ISomethinginner):base(inner){}publicoverridevoidDoSomething(){Console.WriteLine("Before DoSomething");base.DoSomething();Console.WriteLine("After DoSomething");}}// Use the source generator to request a plugin and trigger Wrapper generationMyClassoriginal=new();MyClasswrapped=original.CreatePlugin(plugins: x =>newLoggingPlugin(x));
Generated code:
// Generated plugin base class (by the source generator)// Generate virtual call delegation for all members in ISomething.publicpartialclassSomethingPlugin:ISomething,IDelegable<ISomething>{protectedISomethingInner{get;}publicSomethingPlugin(ISomethinginner){Inner=inner;}publicvirtualvoidDoSomething(){Inner.DoSomething();}}// Generated plugin container (by the source generator)publicclassMyClassPluginContainer{publicChainedProxyBuilder<ISomething>SomethingPlugins{get;}=newChainedProxyBuilder<ISomething>();// ... other ChainedProxyBuilders for other interfaces and base class}// Generated plugin wrapper class (by the source generator)publicpartialclassMyClassWrapper:MyClass{privatereadonlyMyClass_inner;privatereadonlyISomething_innerSomething;publicMyClassWrapper(MyClassinner,MyClassPluginContainerpluginContainer){_inner=inner;_innerSomething=pluginContainer.SomethingPlugins.Execute(inner);// ... apply other plugins from the container}publicoverridevoidDoSomething(){_innerSomething.DoSomething();}publicoverridevoidMyMethod(){_inner.MyMethod();}}
The text was updated successfully, but these errors were encountered:
Overview
Introduce a source generator to facilitate compile-time dynamic behavior injection. This generator will produce "plugin" implementations for classes or interfaces, allowing for behavior extension and customization without altering the original code.
Inspiration
This concept is inspired by the Strix Music SDK's "model plugin" system, which lets developers enhance the SDK by wrapping around and overriding SDK model members. Our goal is to generalize this idea for any class or interface.
Key Features
IDelegable<T>
to delegate to otherT
instances when members aren't overridden.IDelegable<T>.Inner
.Workflow
T
andIDelegable<T>
.T
and anIDelegable<T>
instance during construction.IDelegable<T>.Inner
.base
orInner
to invoke the next plugin or the base class.Applications
Conclusion
This source generator promises a robust method to extend and customize class/interface behavior during compile-time. By crafting "plugin" implementations that can encapsulate and override originals, we're paving the way for a modular and scalable software architecture.
Sources
StrixMusic.Sdk.Plugins.Model
referenceExample
Usage:
Generated code:
The text was updated successfully, but these errors were encountered: