C# Dependency Injection – Using Dependency Injection for Data Objects

cclass-designdependency-injection

I'm just learning about dependency injection, and am stuck on something. Dependency Injection recommends sending dependent classes through the constructor, but I'm wondering if this is necessary for data objects. Since the Unit-Testability is one of the main benefits of DI, would a data object, that only stores data, and not any procedures ever be unit tested, making DI an unnecessary layer of complexity, or does it still help in showing dependencies even with data objects?

Class DO{
    DO(){
        DataObject2List = new List<DO2>();
    }

    public string Field1;
    public string Field2;
    public List<DO2> DataObject2List;
}

Class DO2{
    public DateTime Date;
    public double Value;
}

Best Answer

I'd like to suggest a clarification of some of the terminology you are using here, specifically "dependency" and "dependency injection".

Dependency:

A "dependency" is typically a complex object that performs some functionality that another class may need to depend on. Some classic examples would be a logger or a database accessor or some component that processes a particular piece of business logic.

A data only object like a DTO or a value object are not typically referred to as a "dependency", since they don't perform some needed function.

Once you look at it this way, what you are doing in your example (composing the DO object with a list of D02 objects through the constructor) should not be considered "dependecy injection" at all. It's just setting a property. It's up to you whether you provide it in the constructor or some other way, but simply passing it in through the constructor does not make it dependency injection.

Dependency Injection:

If your DO2 class were actually providing some additional functionality that the DO class needs, then it would truly be a dependency. In that case, the dependent class, DO, should depend on an interface (like ILogger or IDataAccessor), and in turn rely on the calling code to provide that interface (in other words, to 'inject' it into the DO instance).

Injecting the dependency in such a way makes the DO object more flexible, since each different context can provide its own implementation of the interface to the DO object. (Think unit testing.)