I'm having a bit of a moment of indecision here and I'd like some perspective on it.
I'm currently wrapping up objects from a 3rd party API (at home for my own project and at work), and I'm doing my best to adhere as closely to SOLID principles as I can. All of this is written using C#. Just to be clear here: this is not a line of business application, I'm making a framework for reuse that wraps up more complicated details of a 3rd party API.
So my issue is this: I have these objects wrapped up in my concrete instances. We'll call the native objects that are wrapped nA and nB, and the wrappers A and B which hold nA and nB respectively:
class A { private nA _nA }
class B { private nB _nB }
nB can't be created without passing a reference to nA. So, to avoid exposing the nA object to the public, I have a factory method to create wrapper B so it can pass in nA to the constructor of nB. So, first question: I'm assuming this is a proper practice? I don't want to end up with a ton of factories or factory methods if I can help it (there's a fair bit to wrap up).
Now, this is all well and good. I can create A and B no problem because of the above. But, now I have another wrinkle. I have to wrap a method called M1(nB) where the parameter is of type nB, which is stored inside of the B wrapper:
public class A { private nA _nA; public M1(B) { _na.M1( ??? );} }
But, nB is inaccessible. So, what's the best practice to pass nB to the nA.M1() method stored in wrapper A?
I could enforce the use of concrete types, and make nB an internal member on wrapper B like so:
public class B { internal nB { get; private set; } }
But this will introduce tight coupling. Does it matter since nA and nB are tightly coupled anyway?
These kinds of problems always give me a headache, so if anyone could spare some advice, that'd be swell.
Also, while I am trying to adhere to SOLID as best as possible, I am aware they are guidelines. They are not hard set rules or a religion after all. So if I have no choice but to break SOLID principles to get what I need, so be it.
Some code to further illustrate my issue:
interface IGraphics
{
CopyResource(Texture src, Texture dest);
}
interface ITexture
{
// Stuff for textures that have no bearing on this example.
}
class Graphics
: IGraphics
{
// Native object (or object that wraps a native object).
private ID3D11Context1 _d3dContext;
public CopyResource(Texture src, Texture dest)
{
// Do validation, etc...
// How can I do this with interfaces?
// Internals are not allowed on interfaces by the language
_d3dContext.CopyResource(src._d3dTexture, dest._d3dTexture);
}
}
class Texture
: ITexture
{
// Native object (or object that wraps a native object).
private ID3D11Texture2D _d3dTexture;
// Other stuff
}