Design issue (how to avoid to break LSP)
I got the following two interfaces:
interface IModule
{
IModuleResult Invoke(InstallerContext context, IModuleConfiguration config);
}
interface IModuleConfiguration
{
}
The IModuleConfiguration
is used to configure each module. It loads/stores config settings in XML files and are configured through a web app.
The flow is:
Runner -> Load configurations from a single XML file -> Load runner instructions from another XML file -> Invoke selected开发者_高级运维 modules
The design works, but each module only works with it's own configuration. It breaks LSP and I'm wondering if there are any better way to design this.
Using a interface IModule<T> where T : IModuleConfiguration
would not break LSP, but makes it hard to work with each module (as I need to store them as object
in the List
and use reflection to invoke them).
I'm not quite clear how instances of these types come into being, and to what extent they're supposed to be interchangeable. One approach which can be useful in some contexts is to use delegates. For example, suppose some type of object is supposed to provide a method to save its state and later restore it. If the state is supposed to be restored to the same object from which it was saved, the 'save context' routine could return a delegate which, when executed, will restore the object's state. The delegate could contain any type of data whatsoever, but all the code would be type-safe.
Other options would be to make IModuleConfiguration generic with respect to the type of module it configures, and have IModuleConfiguration contain a ConfigureModule or InvokeModule method (which would in turn pass itself to the module's Configure or Invoke method), or have an IConfiguredModule interface, whose invocation method wouldn't say anything about the configuration (instances of the class would be expected to combine a module with an appropriate configuration).
Which approach would be most suitable would depend upon how the various instances are created and used.
精彩评论