0

I have some reusable UserControls, inside those UserControls i want to access some service instances which i registered inside bootstrapper.

I cannot do constructor injection because those user controls are used directly inside xaml, so i tried to access ServiceLocator.Current but it threw exception.

So what is the best practice for accessing registered service instances inside user controls which you cannot do constructor injection as WPF wants parameterless constructor to load them inside xaml.

(Btw, I am using UnityBootstrapper)

Joe Gage
  • 33
  • 9
  • "inside those UserControls" means in code-behind? What prevents you from using an (auto-wired) view model (that has everything injected in ist constructor)? – Haukinger Dec 18 '17 at 12:28
  • Where are your UserControls located? In the shell window? – mm8 Dec 18 '17 at 16:22
  • @Haukinger, "using an auto-wired viewmodel and using constructor injection" is my fallback idea. That means if i cannot find any other solution, i will go that way. And I wonder how all Prism people do this kind of work, what is the best practice. – Joe Gage Dec 18 '17 at 16:50
  • @mm8, I use those controls inside views which is then loaded in shell window. – Joe Gage Dec 18 '17 at 16:52
  • 1
    @Joe: I'd scrap the code-behind. If you need to access services and whatever from your code-behind, you're most likely doing stuff that should be done elsewhere. Try to constrain yourself to view-only things, that cannot be done elsewhere... – Haukinger Dec 18 '17 at 17:47
  • @Haukinger, taking the auto-wired viewmodel approach leads to passing data problem like in the question: https://stackoverflow.com/questions/34375080/synchronizing-dependency-properties-view-with-properties-viewmodel – Joe Gage Dec 19 '17 at 11:01
  • If ServiceLocator.Current returns a null reference you are doing something wrong. Please provide a repo of your issue: https://stackoverflow.com/help/mcve – mm8 Dec 19 '17 at 15:11

1 Answers1

0

You can create a DependencyProperty IUnityContainer and you give your control an instance to it in xaml:

<local:MyControl UnityContainer="{Binding Container}"/>

Now you can access it inside the MyControl. Will this do?

My team likes to use a static reference to the container, but we are allowed to use it only inside converters. Perhaps you could use that too in this case:

<local:MyControl UnityContainer="{UnityContainer}"/>

This is what you need to make this option work:

public static class MarkupExtensionHost
{
    public static IUnityContainer Container { get; set; }
}

public class UnityContainerExtension : MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return MarkupExtensionHost.Container;
    }
}
Milan
  • 616
  • 5
  • 11
  • So your second option (static reference) is same as using ServiceLocator.Current. But it does not work. I wonder why. – Joe Gage Dec 18 '17 at 12:26
  • ilspy shows that ServiceLocator.Current returns ServiceLocator.currentProvider, which is set in the method SetLocatorProvider. Mayhaps we are expected to call this method to set it up before using .Current? (ServiceLocator.SetLocatorProvider) – Milan Dec 18 '17 at 12:46
  • UnityBootstrapper already sets Servicelocator.Current. And I can already use it inside viewmodels. But when it comes to custom user controls, I cannot get Servicelocator.Current instance. – Joe Gage Dec 18 '17 at 14:16
  • Hmm. Does my static reference work? Are we talking about a nullref exception or some other in your usercontrol-code-behind? Did you try passing services in xaml using dependencyproperties? – Milan Dec 18 '17 at 14:36
  • No because I dont think its a good practice to pass the UnityContainer around with dependency properties. – Joe Gage Dec 18 '17 at 15:58
  • if you cant even use MarkupExtensionHost.Container inside of yourControl.cs, then the only thing left is that the container didnt yet exist at the point you are creating your control inside some view. can you try to call MarkupExtensionHost.Container somewhere other than yourControl.cs constructor? perhaps on some button click inside the control? also, is it a null ref exception? – Milan Dec 18 '17 at 17:41