如果您不想在项目之间使用引用,可以考虑使用工厂/抽象工厂。
您的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文件等中有许多不同的数据访问类,因此你可以在业务层为每个定义一个工厂。请注意,保留HTML标签。
使用抽象工厂
工厂可以包含更多关于数据层细节的逻辑,或者作为抽象工厂向业务逻辑层提供一组单独的工厂。
业务逻辑层
您也可以在业务逻辑层中拥有一个抽象工厂,例如
public interface IPlatformFactory
{
IDataAccessFactory GetDataAccessFactory();
IPricingFactory GetPricingFactory();
}
使用具体工厂。
public class WebPlatformFactory : IPlatformFactory
{
IDataAccessFactory GetDataAccessFactory()
{
return new XmlDataAccessFactory();
}
IPricingFactory GetPricingFactory()
{
return new WebPricingFactory();
}
}
你可能还有其他具体的工厂,比如 RetailPlatformFactory
等。
你的 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
,因此可以将其移动到数据层。因此,数据层类将会是:
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并不了解数据层/访问,它只是将工厂创建交给业务层,后者持有数据(和定价)的引用。
一些推荐阅读:
组合根
实现抽象工厂
自信地组成对象图