我正在使用Ninject进行依赖注入,并且在传递基本类型时我已经很好地工作了,但是当我开始传递自定义对象类型时,我不确定构建应用程序的最佳方法。
这是一个简单的例子。我有4个项目:Main,Project A,Project B和Interfaces。主要参考ProjectA,ProjectB和Interfaces以及Project A和ProjectB参考接口。
在Interfaces中我定义了一个接口IClassA,它有一个返回int的方法。
public interface IClassA
{
int ReturnFundamental();
}
在ProjectA中,我有ClassA,它实现了IClassA。
public class ClassA : IClassA
{
public int ReturnFundamental()
{
return 1;
}
}
ProjectB包含ClassB,它接受IClassA作为基于构造函数的依赖注入。它还提供了一种方法,允许我调用IClassA中定义的方法并在ClassA中实现。
public class ClassB
{
private readonly IClassA classA;
public ClassB(IClassA classA)
{
this.classA = classA;
}
public void GetObject()
{
Console.WriteLine(classA.ReturnFundamental());
}
}
Main项目设置Ninject,将IClassA绑定到ClassA,实例化ClassB的实例并在ClassB上调用方法。
static void Main(string[] args)
{
IKernel kernel = new StandardKernel();
kernel.Bind<IClassA>().To<ClassA>();
var classB = kernel.Get<ClassB>();
classB.GetObject();
Console.Read();
}
这一切都很好,ClassB可以调用ClassA中的方法并返回值。但是,如果我不想返回基本类型,而是想返回我定义的自定义对象,那么最好的方法是什么?
如果我没有弄错,那么IClassA,ClassA和ClassB都需要对这个对象的引用,并且在与ClassA或ClassB相同的项目中定义它会导致依赖注入被用来避免的耦合。
所以我能想到的唯一解决方案是:
声明Interfaces项目中的所有对象
创建另一个项目以放置用于在接口之间传递数据的所有对象。
创建一个新项目,其中包含类之间单个交互所需的所有对象,其中每个交互都有自己引用的项目,其中包含所需的所有对象。
我在第一个选项中看到的问题是,不清楚哪些对象被哪些类使用,我担心Interfaces项目会变得太大,在一个位置包含太多信息。
第二个选项与第一个选项共享相同的问题,因为它不清楚哪些对象被哪些类使用,但至少它将接口与仅用于传递数据的对象分开。然而,它会在项目之间添加更多的引用(假设每个接口至少传递一个对象)每个接口,并且实现该接口或使用该接口的每个类都需要对新项目的引用。
第三个选项至少可以清楚地说明哪些类交互需要哪些对象,因为它们都被组合在一起,但是这会导致很多项目被创建。
我认为这是一个很好的解决方案,因为它必定是一个非常常见的问题,但我不确定大型项目的最佳实现。
答案 0 :(得分:1)
无需创建界面项目。 通常做的是将实现(-details)声明为internal,将interface声明为public。例如。
public class PersonInfo
{
string FirstName { get; set; }
string Surname { get; set; }
Address Address { get; set; }
}
public interface IPersonSearchService
{
IEnumerable<PersonInfo> Search(string keyword);
}
internal class PersonSearchService : IPersonSearchService
{
....
}
现在添加一个NinjectModule:
public class PersonSearchServiceModule : NinjectModule
{
public override void Load()
{
this.Bind<IPersonSearchService>().To<PersonSearchService>();
}
}
并在Composition Root(Application Project,Main Project,.. whatchamacallit)中加载模块,由kernel.Load<PersonSearchServiceModule>()
显式加载Module
或kernel.Load(IEnumerable<Assembly>)
一个(或多个)程序集加载{{ 1}}重载。
使用Feature-Namespaces也是一个好主意。