如果您不想要项目之间的引用,您可以查看工厂/抽象工厂。
您的 UI 了解您的业务层,因此您希望在业务层中定义一个工厂,它知道如何使用数据层。然后,您可以在合成根(本示例中的 UI 项目)中处理所有 DI。
下面是一个使用控制台应用程序作为 UI 的简单示例,坚持您在问题中所述的参考文献
数据层
public interface IDataAccess
{
string GetData();
}
public class XmlDataAccess : IDataAccess
{
public string GetData()
{
return "some data";
}
}
业务层
public interface IDataAccessFactory
{
IDataAccess GetDataAccess();
}
public class XmlDataAccessFactory : IDataAccessFactory
{
public IDataAccess GetDataAccess()
{
return new XmlDataAccess();
}
}
public class BusinessLogic
{
IDataAccessFactory dataAccessFactory;
public BusinessLogic(IDataAccessFactory dataAccessFactory)
{
this.dataAccessFactory = dataAccessFactory;
}
public void DoSomethingWithData()
{
IDataAccess dataAccess = dataAccessFactory.GetDataAccess();
Console.WriteLine(dataAccess.GetData());
}
public string GetSomeData()
{
IDataAccess dataAccess = dataAccessFactory.GetDataAccess();
return dataAccess.GetData();
}
}
UI
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IDataAccessFactory, XmlDataAccessFactory>();
var logic = container.Resolve<BusinessLogic>();
logic.DoSomethingWithData();
string useDataInUI = logic.GetSomeData();
Console.WriteLine("UI " + useDataInUI);
Console.ReadKey();
}
这是一个人为的例子,所以看起来像是毫无意义的抽象,但如果有一个现实世界的例子,它会更有意义。
例如您的数据层数据库、xml 文件等中可能有一堆不同的数据访问类,因此您可以为业务层中的每个类定义一个工厂。
使用抽象工厂
工厂可以包含更多有关数据层实质的逻辑,或者作为抽象工厂向业务逻辑层提供一组单独的工厂。
业务层
相反,您可能在业务层中有一个抽象工厂,例如
public interface IPlatformFactory
{
IDataAccessFactory GetDataAccessFactory();
IPricingFactory GetPricingFactory(); // might be in the business project, or another project referenced by it
}
有一个混凝土工厂
public class WebPlatformFactory : IPlatformFactory
{
IDataAccessFactory GetDataAccessFactory()
{
return new XmlDataAccessFactory();
}
IPricingFactory GetPricingFactory()
{
return new WebPricingFactory(); // not shown in the example
}
}
(您可能还有其他具体工厂,例如RetailPlatformFactory
, etc.)
Your BusinessLogic
类现在看起来像
public class BusinessLogic
{
IPlatformFactory platformFactory;
public BusinessLogic(IPlatformFactory platformFactory)
{
this.platformFactory = platformFactory;
}
public void DoSomethingWithData()
{
IDataAccessFactory dataAccessFactory = platformFactory.GetDataAccessFactory();
IDataAccess dataAccess = dataAccessFactory.GetDataAccess();
Console.WriteLine(dataAccess.GetData());
}
public string GetSomeData()
{
IDataAccessFactory dataAccessFactory = platformFactory.GetDataAccessFactory();
IDataAccess dataAccess = dataAccessFactory.GetDataAccess();
return dataAccess.GetData();
}
}
数据层
您的业务层不再需要提供IDataAccessFactory
到您的 UI,以便您可以将其移动到本示例中的数据层中。所以数据层类是
public interface IDataAccess
{
string GetData();
}
public class XmlDataAccess : IDataAccess
{
public string GetData()
{
return "some data";
}
}
public interface IDataAccessFactory
{
IDataAccess GetDataAccess();
}
public class XmlDataAccessFactory : IDataAccessFactory
{
public IDataAccess GetDataAccess()
{
return new XmlDataAccess();
}
}
UI
现在,您可以在 UI 中配置容器并执行类似的操作:
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IPlatformFactory, WebPlatformFactory>();
var logic = container.Resolve<BusinessLogic>();
logic.DoSomethingWithData();
string useDataInUI = logic.GetSomeData();
Console.WriteLine("UI " + useDataInUI);
Console.ReadKey();
}
然后,UI 对数据层/访问一无所知,它只是将工厂创建移交给业务层,该业务层保存数据(和定价)引用。
一些推荐阅读:
成分根 http://blog.ploeh.dk/2011/07/28/CompositionRoot/
实现抽象工厂 http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/
自信地构建对象图 http://blog.ploeh.dk/2011/03/04/Composeobjectgraphswithconfidence/