I have some code I need to restructure. The code calls into some third-party (neighboring department on a different tech stack) methods to do execute some evaluations on some data. There are several of these methods, which work similarly on a technical level, but do different functional work, so they are hidden behind this interface.
public interface IExecutor : IDisposable
{
public void Execute(string workingDirectory);
}
public interface IAlphaExecutor : IExecutor { }
public interface IBetaExecutor : IExecutor { }
// Alpha coming from the 3rd-party nuget and got wrapped like this
public class AlphaImplementation : Alpha, IAlphaExecutor
{
public void Execute(string workingDirectory)
=> Alpha(workingDirectory);
}
Sharing the IExecutor
base-interface allowed us to write some code around it (preparing data, montioring, switching async<->sync context) for the general case and then using the desired interface for the functional task we needed.
Now the department delivering those implementations changed some things up and ended with all of them being in one class. As it does some heavy work on initialization I'd like to also consolidate my wrapper-Implementations into one class (and have one instance of that class being managed by Autofac). However, as both interfaces, IAlphaExecutor
and IBetaExecutor
come form the same base interface I can't create multiple implementations of execute:
public class CollectedImplementation : AlphaAndBeta, IAlphaExecutor, IBetaExecutor
{
public void Execute(string workingDirectory) => ... //Implements both Interfaces
public void IAlphaExecutor.Execute(string workingDirectory) => ... // CS0539: not a member of interface
}
Is there a neat way around this? Or do I need to restructure my interfaces and the code around it. And if so, are there some initial design pitfalls we've fell for that led to this place?
Since the Execute
function in IAlphaExecutor
and IBetaExecutor
was originally implemented from the IExecutor
interface, the IExecutor
interface kind of "owns" the function.
When you implement the IAlphaExecutor
interface, what you're actually doing under the hood is implementing the IExecutor
interface as well as everything in the IAlphaExecutor
interface. In your class, void IAlphaExecutor.Execute
is the same as void IExecutor.Execute
. Effectively, its being implemented "through" the IAlphaExecutor
class.
To get around this, you would have to copy the Execute
method inside IExecutor
into the IAlphaExecutor
and IBetaExecutor
interfaces.
Instead of:
public interface IExecutor
: IDisposable
{
public void Execute(string workingDirectory);
//anything else in the IExecutor interface not detailed in your question
}
public interface IAlphaExecutor : IExecutor { }
public interface IBetaExecutor : IExecutor { }
You would have:
public interface IExecutor
: IDisposable
{
//anything else in the IExecutor interface not detailed in your question
}
public interface IAlphaExecutor
: IExecutor
{
public void Execute(string workingDirectory);
}
public interface IBetaExecutor
: IExecutor
{
public void Execute(string workingDirectory);
}
If you have nothing else in your IExecutor interface, you could either leave if there for clarity or remove it and replace all occurrences of where it is implemented with the IDisposable
interface.