I am trying to build a plugin engine. The only requirement is that a plugin must implement two types: ISettings
and IPlugin
from the contract.cs
below. A basic implementation of a plugin can be found in plugin.cs
.
The main application will scan for assemblies implementing these types, creates instances of them and calls the standard Start()
method.
It works fine, but I am missing any compile time check because I cannot correctly cast the instances to the desired types in main.cs
(I know nothing about plugin.cs
in the main app), that's why I am using dynamic
.
The main reason for using a generic type is to give access to implementor of plugin.cs
to his TSettings
type. I could use IPlugin<ISettings>
instead but this will oblige the implementor to write Start(ISettings settings)
which makes TSettings
unusable without a cast.
Another approach was to follow the official IOptions<TSettings>
pattern, but the settings object cannot be injected into constructor because settings are built or modified after object creation.
I there any better way to design the contract or to obtain a strong typed reference in main.cs
instead of dynamic?
Please note that this is a stripped down example to illustrate the principle, in reality the plugin interface is more complex, TSettings
is used in more places and I am using dependency injection instead of the classic Activator
.
contract.cs
interface ISettings {}
interface IPlugin<TSettings> where TSettings: ISettings
{
void Start(TSettings settings);
}
plugin.cs
class SomeSettings: ISettings {}
class SomePlugin<SomeSettings> : IPlugin<SomeSettings>
{
void Start(SomeSettings settings) { }
}
main.cs
void Load()
{
Type settingsType = ... // extract settings type from plugin.dll
Type pluginType = ... // extract plugin type from plugin.dll
dynamic settings = Activator.CreateInstance(settingsType);
//all I know is that settings can be cast to ISettings
dynamic plugin = Activator.CreateInstance(pluginType)
//all I know is that plugin can be cast to IPlugin<UnknownSettings>
plugin.Start(settings)
//it works but plugin being dynamic, I can write anything here.
}
Aucun commentaire:
Enregistrer un commentaire