How do I inject a constructor dependency into a Vi

2019-05-09 06:15发布

问题:

I have a ViewModel and I want to inject another Class into it. I am using Visual Studio with the latest version of Xamarin. I'm using Autofac for registering en resolving dependencies. But I'm new to it and I'm facing a problem which I can't find the solution to, even though it's probably simple.

This is the Class in which I want to inject another Class:

public IMessagingCenterWrapper MessagingCenterWrapper;

public LoginViewModel(IMessagingCenterWrapper messagingCenterWrapper){
            MessagingCenterWrapper = messagingCenterWrapper;
        }

Then in entry point of the app I have a function which initializes the container which registers and resolves dependencies

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>();
        }

But I get an error when building at the line in the login View:

 BindingContext = new LoginViewModel();

I'm getting the error because I don't initialize the parameter in the call.

But if I do that won't I destroy the whole principle of the IoC pattern. Eventually new class calls will be nested with other dependencies and I want to avoid that.

So my question is: how do I actually inject the the class parameter in the constructor?

回答1:

This is actually a service locator injection, since the injected element is a messaging center service. That's good news.

You don't have to pass in service constructors to view model constructors. Just request the service where you need it:

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

Don't stick the view models into AutoFac unless they are indeed global. There are a lot of problems with this sort of fake IOC.

To make it easier overall, how about this:

// 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 !!!! }
}  

The complete code for these remarks is at https://github.com/marcusts/xamarin-forms-annoyances. See the solution called AwaitAsyncAntipattern.sln.

The GitHub site also provides links to a more detailed discussion on this topic.