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