I'm currently working on a project where I'm parsing an external file to an abstracted object like so:
public interface IMapConverter
{
IMap Convert(IMapFile file);
}
public interface IMapFile
{
void Load(string filePath);
string Json { get; }
}
My plan was to abstract the loading of the file by using the IMapFile implementation and creating the StreamReader inside that implementation. I would then pass that on to the IMapConverter.Convert method. Would that be a correct approach and maintain testability? Would it for example be wrong to pass the string directly to the IMapConverter and handle it there?
I don't see a problem with doing what you're suggesting, i.e. having the concrete IMapConverter
create an instance of your concrete IMapFile
because they're both on the same layer of your application.
The rule, as I understand it, is that one class that implements a dependency interface can "know" about an implementation of another interface as long as they're on the same layer of your application; once you're working between layers, you want to inject your dependencies, i.e. your concrete implementations, into the layer below it.
I've been studying the onion architecture which I would highly recommend to anyone who is looking to create loosely-coupled, highly-testable applications. This notion of dependencies knowing about one another as long as they're on the same layer is discussed on that site.