使用控制反转范例创建自定义对象列表
Create a list of custom objects with Inversion of Control paradigm
我想将依赖注入和控制反转应用到我的日常开发中。假设我有一个 SomeObject
的对象类型(实现接口 ISomeObject
)。我有一个 class,它使用这个名为 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
class 才能具体施放。
2。将我的 IoC 容器实例传递给 Data
的构造函数 ,然后使用 container.Resolve<ISomeObject>()
解析对象类型。如果不使用我的 IoC 容器,这将使 GetSomeObjects()
方法的单元测试变得困难。我读过我不应该在单元测试期间使用 IoC 容器,应该手动将我需要的内容传递到方法中。
3。传递已实例化为 SomeObject
的 ISomeObject
对象 - 然后我将使用它通过一些内置方法创建对象,例如 SomeObject.GenerateList(IDataReader reader)
.
您可以将对象的创建委托给其他人;
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
只依赖于抽象而不依赖于具体化。这些可以是运行时组合根中的 determined/configured。
我想将依赖注入和控制反转应用到我的日常开发中。假设我有一个 SomeObject
的对象类型(实现接口 ISomeObject
)。我有一个 class,它使用这个名为 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
class 才能具体施放。
2。将我的 IoC 容器实例传递给 Data
的构造函数 ,然后使用 container.Resolve<ISomeObject>()
解析对象类型。如果不使用我的 IoC 容器,这将使 GetSomeObjects()
方法的单元测试变得困难。我读过我不应该在单元测试期间使用 IoC 容器,应该手动将我需要的内容传递到方法中。
3。传递已实例化为 SomeObject
的 ISomeObject
对象 - 然后我将使用它通过一些内置方法创建对象,例如 SomeObject.GenerateList(IDataReader reader)
.
您可以将对象的创建委托给其他人;
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
只依赖于抽象而不依赖于具体化。这些可以是运行时组合根中的 determined/configured。