如何使用 Xamarin 和 Autofac 将构造函数依赖项注入 ViewModel?

Posted

技术标签:

【中文标题】如何使用 Xamarin 和 Autofac 将构造函数依赖项注入 ViewModel?【英文标题】:How do I inject a constructor dependency into a ViewModel using Xamarin and Autofac? 【发布时间】:2018-04-27 12:27:15 【问题描述】:

我有一个 ViewModel,我想向其中注入另一个类。我正在将 Visual Studio 与最新版本的 Xamarin 一起使用。我正在使用 Autofac 注册和解析依赖项。但我是新手,我遇到了一个我找不到解决方案的问题,即使它可能很简单。

这是我要注入另一个类的类:

public IMessagingCenterWrapper MessagingCenterWrapper;

public LoginViewModel(IMessagingCenterWrapper messagingCenterWrapper)
            MessagingCenterWrapper = messagingCenterWrapper;
        

然后在应用程序的入口点,我有一个函数来初始化容器,该容器注册并解决依赖关系

static IContainer container get; set; 

public App ()
        
            InitializeComponent();

            InitializeIOCContainer();
        

void InitializeIOCContainer()
        
            var builder = new ContainerBuilder();
            builder.RegisterType<LoginViewModel>();
            builder.RegisterType<MessagingCenterWrapper>().As<IMessagingCenterWrapper>();
            container = builder.Build();

            var wrapper = container.Resolve<IMessagingCenterWrapper>();
            var viewModel = container.Resolve<LoginViewModel>();
        

但是在登录视图中的行构建时出现错误:

 BindingContext = new LoginViewModel();

我收到错误是因为我没有在调用中初始化参数。

但如果我这样做,我不会破坏 IoC 模式的整个原则。最终新的类调用将与其他依赖项嵌套,我想避免这种情况。

所以我的问题是:我如何在构造函数中实际注入类参数?

【问题讨论】:

在执行BindingContext = new LoginViewModel(); 时,您根本没有使用 DI 容器 @Fildor 你能解释一下它是如何完成的吗?因为容器是App入口点类的私有变量,在View中调用BindingContext = new LoginViewModel(); 我承认我不知道 Autofac 的最佳实践。但我看到容器在 App 中是静态的。因此,您可以添加一个静态属性来解析 getter 中的实例。 调用Resolve&lt;T&gt; 不是反模式。你误会了。您需要调用Resolve&lt;T&gt; 才能让Autofac 为您创建对象。他们试图告诉你的是,从任何地方调用Resolve&lt;T&gt;,但 Composition Root 一种反模式。为了能够解析根对象,您将必须调用Resolve&lt;T&gt;。没有办法解决这个问题。 在 WPF 中可以做的是解析视图,然后调用 view.Show();。视图会将 LoginViewModel 作为构造函数中的参数,然后在第一行中将 DataContext 设置为 LoginViewModel 参数。 【参考方案1】:

这实际上是一个服务定位器注入,因为注入的元素是一个消息中心服务。这是个好消息。

您不必传入服务构造函数来查看模型构造函数。只需在您需要的地方请求服务:

public LoginViewModel()  
  
   MessagingCenterWrapper = App.Container.Resolve<IMessagingCenterWrapper>();  
  

除非视图模型确实是全局的,否则不要将视图模型粘贴到 AutoFac 中。这种假国际奥委会有很多问题。

为了整体上更容易,这样怎么样:

// MUST BE PUBLIC 
public static IContainer Container get; set; 

static App()  

   InitializeIOCContainer();  
 

public App () 
    
   InitializeComponent(); 


private static void InitializeIOCContainer() 
    
   var builder = new ContainerBuilder();    
   builder.RegisterType<MessagingCenterWrapper>().As<IMessagingCenterWrapper>();
   Container = builder.Build();

   // Don't stick view models in the container unless you need them globally, which is almost never true !!!

   // Don't Resolve the service variable until you need it !!!! 
  

这些备注的完整代码位于https://github.com/marcusts/xamarin-forms-annoyances。请参阅名为 AwaitAsyncAntipattern.sln 的解决方案。

GitHub 站点还提供了有关此主题的更详细讨论的链接。

【讨论】:

服务定位器是一种既定的反模式。

以上是关于如何使用 Xamarin 和 Autofac 将构造函数依赖项注入 ViewModel?的主要内容,如果未能解决你的问题,请参考以下文章

如何将构面标签移动到图表顶部?

如何在 Avalonia.ReactiveUI 中使用 Autofac 作为 DI 容器?

如何使用 Autofac 注入相同的 DbContext 实例来处理 HTTP 请求而不会导致并发问题?

使用 FluentNhibernate 和 Autofac 的映射接口

如何运用AutoFac在WebAPI中注入多个接口

如何创建一个Quartz.NET的工作,需要注射autofac