I have recently been trying to adapt Dependency Injection and Inversion of Control into my daily development (I just started learning about it this past Friday, as well as getting familiar with reflection and generics, so please be gentle), and I have hit a bit of a snag on how to handle something elegantly.
Let us take the following example. Say I have an object type of SomeObject (implements the interface ISomeObject). I have a class which consumes this object called Data which implements the IData interface.
public interface ISomeObject
{
int ID;
string Name;
bool IsAwesome;
void DoSomeStuffIfAwesome();
}
public Class SomeObject : ISomeObject
{
int ID;
string Name;
bool IsAwesome;
void DoSomeStuffIfAwesome() { /*stuff happens here*/ }
}
public interface IData
{
List<ISomeObject> GetSomeObjects();
}
public Class Data : IData
{
List<ISomeObject> GetSomeObjects()
{
List<ISomeObject> objects = new List<ISomeObject>; // ??? Maybe and cast later?
//do some SQL stuff and get a SqlDataReader object called reader
while(reader.Read())
{
//ISomeObject someObj = ???
//Read into the someObj.ID, someObj.Name and someObj.IsAwesome fields
objects.add(someObj);
}
return objects;
}
}
The purpose of the GetSomeObjects() method in Data.cs is to produce a list of ISomeObject objects to be used elsewhere. But, being true to IoC, I don't want Data.cs to have anything related to SomeObject hardcoded into it, so I want to use some form of Dependency Injection to resolve the issue at runtime.
So now my question: What is the best way to handle this. I've thought of a few possibilities, and if all of them are WAY off track please let me know.
Option A) Pass into the constructor of Data an instance of SomeObject so that I can get its type with .GetType(), store that into a private System.Type variable in Data.cs, and use Activator.CreateInstance in the loop to create new objects to be added to the list? The problem here is that Data would need to know about the SomeObject class specifically to cast it, if I understand it correctly.
Option B) Pass into the constructor of Data an instance of my IoC container, and just resolve the object type using container.Resolve(). My only concern here is that this code would make unit testing the GetSomeObjects() method difficult without utilizing my IoC container. I've read in more than 1 place that I should NOT utilize my IoC container during unit testing, and should manually pass in what I need into methods; if this is wrong please let me know!
Option C) Pass into the constructor of Data an ISomeObject object that has been instantiated as a SomeObject. Then use that to create the object I need via some built in method (for example: SomeObject.GenerateList(IDataReader reader)).
Option D) ... ???
As you can see, I'm dying trying to wrap my head around the proper way to handle this abstraction, and could definitely use some assistance! Any critiques or otherwise, I am all ears.
Thanks!
Aucun commentaire:
Enregistrer un commentaire