At first I was a little confused, because in this case the computer does the calculations, and the devices get the result. So, I understand that you need different implementations of something on the PC, not the devices themselves.
The real trick here is not to use an interface or inheritance - you already understood that. The trick gets the right type of implementation, and you use the factory for this part.
But you also need to solve the issue of inheritance and interface.
Use inheritance only if this “something” really is part of a common, but also significant family. Inheritance must have a very strong "eat" element.
OTOH there may be many objects that could do the calculations, but you would not want to create a family. The composition is useful here. In order to inherit this, you need to have a common base class. Here you can use composition so that each object can use a common interface to allow the computer to perform calculations.
I suggest this approach.
You should have a link to a common, common interface, IDoCalculation or some one that defines the method signature, which will be called in the same way for any device.
Then you need to get a specific device implementation for this interface, which means that each device can have a different implementation. Create a class for each type of device / implementation.
Now the trick is to get the class you need without knowing what it is. To save hidden data again and make the method a generic call, you can create a parameterized Factory. This factory accepts a parameter that describes which device requires computing for the PC. Then he interprets this parameter and on the basis of this creates a specific class that implements IDoCalculation. It is back and everything is ready.
I leave this for you to figure out how these objects should be organized into different assemblies ...
//Common interface public interface IDoCalculation { //Use whatever method signatures you need int DoCalculation(); } public class DeviceImplementation1 : IDoCalculation {