将 Autofac 添加到 WPF MVVM 应用程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43689124/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Adding Autofac to WPF MVVM application
提问by Ben
I can't seem to find an solution to this problem. I've seen several questions about this, but none really give me a solution. I am totally new to Autofac and haven't really done much WPF + MVVM, but know the basics.
我似乎无法找到解决此问题的方法。我已经看到了几个关于这个的问题,但没有一个真正给我一个解决方案。我对 Autofac 完全陌生,并没有真正做过多少 WPF + MVVM,但了解基础知识。
I have a WPF application (using ModernUI for WPF) which I'm trying to add Autofac to, and I am having a hard time figuring out how to resolve my services within all the views, since they have no access to my container. I have a main view, which is my entry point, where I set up my container:
我有一个 WPF 应用程序(使用 ModernUI for WPF),我正在尝试将 Autofac 添加到其中,但我很难弄清楚如何在所有视图中解析我的服务,因为它们无法访问我的容器。我有一个主视图,这是我设置容器的入口点:
public partial class MainWindow : ModernWindow
{
IContainer AppContainer;
public MainWindow()
{
SetUpContainer();
this.DataContext = new MainWindowViewModel();
InitializeComponent();
Application.Current.MainWindow = this;
}
private void SetUpContainer()
{
var builder = new ContainerBuilder();
BuildupContainer(builder);
var container = builder.Build();
AppContainer = container;
}
private void BuildupContainer(ContainerBuilder builder)
{
builder.RegisterType<Logger>().As<ILogger>();
...
}
}
The problem I'm having is figuring out how I can resolve my logger and other services within my other views, where I inject all my dependencies through the ViewModel constructor, like so:
我遇到的问题是弄清楚如何在我的其他视图中解决我的记录器和其他服务,我通过 ViewModel 构造函数注入我的所有依赖项,如下所示:
public partial class ItemsView : UserControl
{
private ItemsViewModel _vm;
public ItemsView()
{
InitializeComponent();
IFileHashHelper fileHashHelper = new MD5FileHashHelper();
ILibraryLoader libraryLoader = new LibraryLoader(fileHashHelper);
ILogger logger = new Logger();
_vm = new ItemsViewModel(libraryLoader, logger);
this.DataContext = _vm;
}
}
Some views have a ridiculous amount of injected parameters, and this is where I want Autofac to come in and help me clean things up.
有些视图注入了大量的参数,这就是我希望 Autofac 进来帮助我清理的地方。
I was thinking of passing the container to the ViewModel and storing it as a property on my ViewModelBase class, but I've read that this would be an anti-pattern, and even then I don't know if that would automatically resolve my objects within the other ViewModels.
我正在考虑将容器传递给 ViewModel 并将其作为属性存储在我的 ViewModelBase 类中,但我读到这将是一个反模式,即使那样我也不知道这是否会自动解析我的对象在其他 ViewModel 中。
I managed to put together a simple Console Application using Autofac
我设法使用 Autofac 组合了一个简单的控制台应用程序
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Cleaner>().As<ICleaner>();
builder.RegisterType<Repository>().AsImplementedInterfaces().InstancePerLifetimeScope();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
ICleaner cleaner = container.Resolve<ICleaner>();
cleaner.Update(stream);
}
}
}
but that was simple since it has a single entry point.
但这很简单,因为它只有一个入口点。
I'd like some ideas on how to add Autofac to my WPF app. I'm sure that I'm doing something wrong. Your help is appreciated.
我想要一些关于如何将 Autofac 添加到我的 WPF 应用程序的想法。我确定我做错了什么。感谢您的帮助。
采纳答案by AwkwardCoder
Expanding on my comment above:
扩展我上面的评论:
I use Autofac with all my WPF MVVM applications, I believe it to be one of the better DI frameworks - this is my opinion, but I think it is valid.
我将 Autofac 与我所有的 WPF MVVM 应用程序一起使用,我相信它是更好的 DI 框架之一 - 这是我的意见,但我认为它是有效的。
Also for me PRISM should be avoided 99% of the time, it's a 'solution looking for a problem' and since most people don't build dynamically composable runtime solutions in WPF it is not needed, i'm sure people would\will disagree.
同样对我来说,99% 的情况下都应该避免 PRISM,这是一个“寻找问题的解决方案”,而且由于大多数人不在 WPF 中构建动态可组合运行时解决方案,因此不需要它,我相信人们会\会不同意.
Like any architectural patterns there is a setup\configuration phase to the application life-cycle, put simply in your case before the first View (window) is shown there will be a whole of setup done for Dependency Injection, Logging, Exception Handling, Dispatcher thread management, Themes etc.
像任何架构模式一样,应用程序生命周期也有一个设置\配置阶段,简单地说,在显示第一个视图(窗口)之前,将为依赖注入、日志记录、异常处理、调度程序完成整个设置线程管理,主题等。
I have several examples of using Autofac with WPF\MVVM, a couple are listed below, I would say look at the Simple.Wpf.Exceptions example:
我有几个使用 Autofac 和 WPF\MVVM 的例子,下面列出了几个,我会说看看 Simple.Wpf.Exceptions 例子:
https://github.com/oriches/Simple.Wpf.Exceptions
https://github.com/oriches/Simple.Wpf.Exceptions
https://github.com/oriches/Simple.Wpf.DataGrid
https://github.com/oriches/Simple.Wpf.DataGrid
回答by Swoogan
You can use a similar technique as your console application:
您可以使用与控制台应用程序类似的技术:
class Program
{
[STAThread]
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Cleaner>().As<ICleaner>();
builder.RegisterType<Repository>().AsImplementedInterfaces().InstancePerLifetimeScope();
// Add the MainWindowclass and later resolve
build.RegisterType<MainWindow>().AsSelf();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var main = scope.Resolve<MainWindow>();
main.ShowDialog();
}
}
}
Be sure to mark Main with [STAThread]. Then in the project's properties, under the Application tab, set the Startup objectto the Program class.
请务必用 标记 Main [STAThread]。然后在项目的属性中,在 Application 选项卡下,将 设置Startup object为 Program 类。
However, I am not certain of the implications of not running App.Run()and of running MainWindow.ShowDialog()instead.
但是,我不确定不跑步App.Run()和跑步的影响MainWindow.ShowDialog()。
To do the same using App.Run(), do the following:
要使用 做同样的事情App.Run(),请执行以下操作:
1) delete StartupUri="MainWindow.xaml"from App.xaml
1)StartupUri="MainWindow.xaml"从 App.xaml 中删除
2) Add the following to App.xaml.cs
2) 将以下内容添加到 App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
var builder = new ContainerBuilder();
builder.RegisterType<Cleaner>().As<ICleaner>();
builder.RegisterType<Repository>().AsImplementedInterfaces().InstancePerLifetimeScope();
// Add the MainWindowclass and later resolve
build.RegisterType<MainWindow>().AsSelf();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var window = scope.Resolve<MainWindow>();
window.Show();
}
}
回答by Travis Illig
WPF doesn't have a natural composition root or easy DI integration. Prismis a pretty common set of libraries specifically intended to bridge that for you.
WPF 没有自然的组合根或简单的 DI 集成。Prism是一组非常常见的库,专门用于为您架起桥梁。
(That's not Autofac specific - it's general guidance for adding DI to WPF apps.)
(这不是 Autofac 特有的——它是将 DI 添加到 WPF 应用程序的一般指南。)

