我希望将依赖注入和控制反转适应我的日常开发。假设我的对象类型为SomeObject
(实现接口ISomeObject
)。我有一个类,它使用这个名为Data的对象来实现IData
接口。
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;
}
}
GetSomeObjects()
方法生成ISomeObject
个对象的列表。但我不希望Data.cs
有任何与SomeObject
硬编码相关的内容。我想要某种形式的依赖注入来解决运行时的问题。处理这个问题的最佳方法是什么?我考虑过以下几点:
1。将SomeObject
的实例传递给Data
的构造函数。这样我可以使用.GetType()
获取其类型,将其存储到私有System.Type
变量中在Data.cs
中,并在循环中使用Activator.CreateInstance
来创建要添加到列表中的新对象。如果我理解正确的话,Data
需要了解专门投射的SomeObject
类。
2。将我的IoC容器的实例传递给Data
的构造函数,然后使用container.Resolve<ISomeObject>()
解析对象类型。如果不使用我的IoC容器,这将使单元测试GetSomeObjects()
方法变得困难。我已经读过,我不应该在单元测试中使用IoC容器,而应该手动将我需要的内容传递给方法。
第3。传递已经实例化为ISomeObject
的SomeObject
对象 - 然后我会使用它通过一些内置方法创建对象,例如SomeObject.GenerateList(IDataReader reader)
。
答案 0 :(得分:2)
您可以将对象的创建委托给其他人;
public interface ISomeObjectFactory {
ISomeObject Create(IDataReader reader);
}
负责创建ISomeObject
using System.Collections.Generic;
using System.Data;
public interface IDbConnectionFactory {
///<summary>
/// Creates a connection based on the given database name or connection string.
///</summary>
IDbConnection CreateConnection(string nameOrConnectionString);
}
public class Data : IData {
private IDbConnectionFactory dbConnectionFactory;
ISomeObjectFactory someObjectFactory;
private string CONNECTION_STRING = "Connection string here";
public Data(IDbConnectionFactory dbConnectionFactory, ISomeObjectFactory objectFactory) {
this.dbConnectionFactory = dbConnectionFactory;
this.someObjectFactory = objectFactory;
}
public List<ISomeObject> GetSomeObjects() {
var objects = new List<ISomeObject>();
//do some SQL stuff and return a data reader
using (var connnection = dbConnectionFactory.CreateConnection(CONNECTION_STRING)) {
using (var command = connnection.CreateCommand()) {
//configure command to be executed.
command.CommandText = "SELECT * FROM SOMEOBJECT_TABLE";
connnection.Open();
using (var reader = command.ExecuteReader()) {
while (reader.Read()) {
//...Logic to populate item
var someObject = someObjectFactory.Create(reader);
if (someObject != null)
objects.Add(someObject);
}
}
}
}
return objects;
}
}
那种方式Data
仅依赖于抽象而不依赖于具体结果。这些可以在运行时在组合根中确定/配置。