我希望在新的解决方案中使用诸如StructureMap的IoC容器。解决方案项目如下:
其中Desktop.Models,BusinessLogic和DataAccess都引用了BusinessObjects。
Desktop.UI项目将是应该配置DI的入口点,但我真的不想仅为DI添加对DataAccess的引用。
我在SO上已经看到了其他一些问题,一个答案是为IoC创建一个单独的项目,引用相关项目,然后从Desktop.UI引用IoC项目。但是,Desktop.UI需要DI配置来实例化视图的演示者,因此不确定单独的项目是否有效。
我已经看到了一些定义Registry类和使用StructureMap扫描功能自动检测Registry类的基本示例。我的第一个想法是将这些Registry类放在他们正在配置的项目中,但这会导致所有项目都必须引用StructureMap。
在分层应用程序中设置DI的推荐方法是什么?
答案 0 :(得分:1)
根据我的经验,我发现我在服务器端代码中使用了一种形式的依赖注入,而在我的客户端代码中使用了一种形式的依赖注入。例如,我最近工作的[叹息] WinForms项目在服务器端使用Unity(业务逻辑,数据访问)和客户端的智能客户端软件工厂(包括winforms的MVP框架)它自己的DI形式。因此,在您的示例中,我会说如果您在尝试让DI框架在应用程序的所有层上工作时遇到困难,那是因为您不应该这样做。你可能有一个案例,你想要有两种形式的DI,一种用于客户端,一种用于服务器。
除此之外,我认为我说大多数DI框架允许您在配置文件中引导您的依赖项。配置文件告诉框架有关您的依赖项的所有内容,包括它们所在的程序集。这意味着您不需要在实例化IoC容器的项目中引用任何实际项目。因此,在我的Framework项目示例中,您将拥有一个实例化IoC容器的单例,并从配置文件中读取所有依赖项。
以下是您的一些链接:
希望其中一些有帮助!
此致
詹姆斯
答案 1 :(得分:1)
对于WindowsForms,我有一个单独的项目来处理我的IoC。我称之为CompositionRoot。
CompositionRoot
(启动项目)的入口点:
public static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
BootsTrapper.Boot();
using (var mainForm = ObjectFactory.GetInstance<IPresenter<IMainView>>())
{
Application.Run((Form)mainForm.CurrentView);
}
}
}
BootsTrapper
负责注册,并且是CompositionRoot
的一部分。
MainViewPresenter显示第一个表单。 MainViewPresenter可以使用包含抽象演示者工厂的外观服务IMainViewPresenterFacade
来显示其他表单。
public class MainViewPresenter : Presenter<IMainView>
{
readonly IArticleRepository _articlesRepository;
readonly IMainViewPresenterFacade _presenterFactory;
readonly IUnitOfWork _unitOfWork;
public MainViewPresenter(IMainView currentView, IArticleRepository articlesRepository, IUnitOfWork unitOfWork,
IMainViewPresenterFacade presenterFactory)
: base(currentView, unitOfWork)
{
_articlesRepository = articlesRepository;
_unitOfWork = unitOfWork;
_presenterFactory = presenterFactory;
Ensure.That(articlesRepository).IsNotNull();
Ensure.That(presenterFactory).IsNotNull();
CurrentView.DetailsClick += View_DetailsClick;
CurrentView.CloseClick += ViewCloseClick;
CurrentView.CreateClick += View_CreateClick;
CurrentView.DeleteClick += View_DeleteClick;
CurrentView.BindModel(_articlesRepository.GetAll().Select(x => new ArticleViewModel { Id = x.ArticleId, Name = x.Description }));
}
public override void Dispose()
{
base.Dispose();
CurrentView.DetailsClick -= View_DetailsClick;
CurrentView.CloseClick -= ViewCloseClick;
CurrentView.CreateClick -= View_CreateClick;
CurrentView.DeleteClick -= View_DeleteClick;
}
void View_DeleteClick(object sender, EventArgs e)
{
var selectedArticle = CurrentView.GetSelectedArticle();
var article = _articlesRepository.GetById(selectedArticle.Id);
_articlesRepository.Delete(article);
_unitOfWork.Commit();
}
void View_CreateClick(object sender, EventArgs e)
{
using (var createPresenter = _presenterFactory.CreateCreatePresenter())
{
ShowDialog(createPresenter.CurrentView, CurrentView);
}
}
void ViewCloseClick(object sender, EventArgs e)
{
CurrentView.Close();
}
void View_DetailsClick(object sender, EventArgs eventArgs)
{
var article = CurrentView.GetSelectedArticle();
if (article == null) return;
using (var detailPresenter = _presenterFactory.CreateDetailPresenter(article))
{
ShowDialog(detailPresenter.CurrentView, CurrentView);
}
}
}
查看我的SimpleMVP项目或此问题Dependency Injection and project structure for Console applications,随时提出进一步的问题:)