This is my locator. For demonstration purposes, I stripped all ViewModels except two. Since I basically need to register all : ViewModelBase
objects, I was thinking of using reflection to do this. The properties of the class itself can't be "created" like this, but the registration can. However, I'm struggling with reflection on generic methods here.
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
using System;
namespace DevExplorer
{
public class ViewModelLocator
{
public WindowMainViewModel WindowMain => SimpleIoc.Default.GetInstance<WindowMainViewModel>();
public WindowAboutViewModel WindowAbout => ServiceLocator.Current.GetInstance<WindowAboutViewModel>(GetKey());
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
//REFACTOR: Get by reflection
SimpleIoc.Default.Register<WindowMainViewModel>();
SimpleIoc.Default.Register<WindowAboutViewModel>();
}
private string GetKey()
{
return Guid.NewGuid().ToString();
}
}
}
Like usually, formulating a proper question required me dig in deeper, so after some time I came up with this code for the ViewModelLocator
constructor. And I would like to share it, since I feel this is an at least somewhat common MVVM Light problem that I haven't found any solution to, yet.
ViewModelBase
are retrieved from all assemblies. Register
method of SimpleIoc
. For now, I have no better idea than to "find" it using .Where
. Please feel free to improve this statement! MakeGenericMethod
with the type of the ViewModelBase
derivate. Type[] viewModels = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => typeof(ViewModelBase).IsAssignableFrom(type) && type != typeof(ViewModelBase))
.ToArray();
MethodInfo registerMethod = typeof(SimpleIoc)
.GetMethods()
.Where(method => method.Name == nameof(SimpleIoc.Default.Register) && method.GetParameters().Length == 0 && method.GetGenericArguments().Length == 1)
.First();
foreach (Type viewModel in viewModels)
{
registerMethod
.MakeGenericMethod(viewModel)
.Invoke(SimpleIoc.Default, new object[0]);
...And with the properties at the top of the ViewModelLocator class: I don't think it can be done with reflection and misusing XAML for this doesn't seem like good practice to me. But, to make life easier, I created a simple method.
The singleton
parameter defines whether or not the instance should be single or get a unique key each time. I defined the MainWindow as singleton in my application and the other ViewModels are not singletons in my scenario.
public WindowMainViewModel WindowMain => GetInstance<WindowMainViewModel>(true);
public WindowAboutViewModel WindowAbout => GetInstance<WindowAboutViewModel>(false);
private static TService GetInstance<TService>(bool singleton)
{
return ServiceLocator.Current.GetInstance<TService>(singleton ? null : Guid.NewGuid().ToString());
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.