Reputation: 17951
I am using Caliburn Micro for WinRT apps. I have registered a service in my App.xaml.cs see sample code below
public sealed partial class App
{
private WinRTContainer _container;
public App()
{
InitializeComponent();
Resuming += AppResuming;
}
protected override void Configure()
{
_container = new WinRTContainer();
_container.RegisterWinRTServices();
_container.Singleton<ISampleService, SampleService>();
//some more viewmodels & services added
}
protected override void PrepareViewFirst(Frame rootFrame)
{
_container.RegisterNavigationService(rootFrame);
}
protected override object GetInstance(Type service, string key)
{
return _container.GetInstance(service, key);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return _container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
_container.BuildUp(instance);
}
}
Now, I have a utility class in which I want to get the instance of this SampleService
.
How can I get the instance?
Upvotes: 0
Views: 2181
Reputation: 1767
In most cases you should avoid pulling things from the container directly. Instead, consider using dependency injection.
For example, if you want to use ISampleService
in SomeUtility
class, which is called from SomeViewModel
, then first you will need to register all three types in the container.
public class AppBootstrapper : BootstrapperBase
{
protected override void Configure()
{
...
_container.Singleton<ISampleService, SampleService>();
_container.Singleton<SomeUtility>();
_container.PerRequest<SomeViewModel>();
}
}
Now, since SomeUtility
depends on ISampleService
, you should create SomeUtility
constructor, which will accept ISampleService
.
class SomeUtility
{
private ISampleService _service;
public SomeUtility(ISampleService service)
{
_service = service;
}
}
And if SomeViewModel
will be using SomeUtility
, then appropriate constructor should be added to SomeViewModel
as well.
class SomeViewModel : Caliburn.Micro.Screen
{
private SomeUtility _utility;
public SomeViewModel(SomeUtility utility)
{
_utility = utility;
}
}
Finally, let's add SomeViewModel
into ShellViewModel
constructor.
class ShellViewModel : PropertyChangedBase, IShell
{
private SomeViewModel _vm;
public ShellViewModel(SomeViewModel vm)
{
_vm = vm;
}
}
That's it! ShellViewModel
will get SomeViewModel
instance, SomeViewModel
will get SomeUtility
and SomeUtility
will have your ISampleService
. And all this will be resolved by Container, so you don't need to create manually new SomeUtility();
or pull from the container IoC.Get<ISampleService>();
.
Also you might be wondering: What if SomeViewModel
should be created on request, for example, when user click "Add" button? Well, I glad you asked. :) For that case you can use a factory method!
Just register it with the container.
public class AppBootstrapper : BootstrapperBase
{
protected override void Configure()
{
...
_container.Handler<IScreen>((x) => x.GetInstance<SomeViewModel>());
}
}
Now you can easily inject it into constructor and use it to create as many instances of SomeViewModel
as needed.
class ShellViewModel : Conductor<IScreen>.Collection.AllActive, IShell
{
private Func<SomeViewModel> _vmFactory;
public ShellViewModel(Func<SomeViewModel> vmFactory)
{
_vmFactory = vmFactory;
}
public void Add()
{
var newVM = _vmFactory();
ActivateItem(newVM);
}
}
Upvotes: 1
Reputation: 16361
The answer from Guerudo works, but you should never use IoC.Get<>
unless you absolutely have to. Using a service locator is considered an anti-pattern.
The right when do get an instance is to use constructor injection. Say you have a MainViewModel, the do this
public class MainViewModel
{
private readonly ISampleService _sampleService;
public MainViewModel(ISampleService sampleService)
{
_sampleService = sampleService
}
}
And use _sampleService anywhere in your ViewModel.
And there is no need for any MEF attributes with Caliburn.Micro.
Upvotes: 2
Reputation: 361
I'm supposing you are using MEF with Caliburn.Micro
So you can get an instance this way :
SampleService service = IoC.Get<ISampleService>();
Hope this will help you.
Upvotes: 2