MVVM Light Locator:注册 ViewModelBase 的所有派生类
MVVM Light Locator: Register all derivates of ViewModelBase
这是我的定位器。出于演示目的,我去除了除两个之外的所有 ViewModel。因为我基本上需要注册所有 : ViewModelBase
对象,所以我正在考虑使用 reflection 来做到这一点。 class本身的属性不能像这样"created",但是注册可以。但是,我正在努力思考这里的泛型方法。
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();
}
}
}
像往常一样,制定一个正确的问题需要我深入挖掘,所以一段时间后我想出了 ViewModelLocator
构造函数的代码。我想分享它,因为我觉得这至少是 有点 常见的 MVVM Light 问题,我还没有找到任何解决方案。
- 首先,从所有程序集中检索所有类型的
ViewModelBase
。
- 然后,我们需要获取
SimpleIoc
的Register
方法。现在,我没有比 "find" 使用 .Where
更好的主意了。 请随时改进此声明!
- 最后,我使用
MakeGenericMethod
和 ViewModelBase
派生类型。
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]);
...以及 ViewModelLocator class 顶部的属性:我不认为它可以通过反射和滥用 XAML 来完成,因为这看起来不太好给我练习。但是,为了让生活更轻松,我创建了一个简单的方法。
singleton
参数定义实例是否应该是单一的,或者每次都获得一个唯一的键。我在我的应用程序中将 MainWindow 定义为单例,而其他 ViewModel 在我的场景中不是单例。
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());
}
这是我的定位器。出于演示目的,我去除了除两个之外的所有 ViewModel。因为我基本上需要注册所有 : ViewModelBase
对象,所以我正在考虑使用 reflection 来做到这一点。 class本身的属性不能像这样"created",但是注册可以。但是,我正在努力思考这里的泛型方法。
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();
}
}
}
像往常一样,制定一个正确的问题需要我深入挖掘,所以一段时间后我想出了 ViewModelLocator
构造函数的代码。我想分享它,因为我觉得这至少是 有点 常见的 MVVM Light 问题,我还没有找到任何解决方案。
- 首先,从所有程序集中检索所有类型的
ViewModelBase
。 - 然后,我们需要获取
SimpleIoc
的Register
方法。现在,我没有比 "find" 使用.Where
更好的主意了。 请随时改进此声明! - 最后,我使用
MakeGenericMethod
和ViewModelBase
派生类型。
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]);
...以及 ViewModelLocator class 顶部的属性:我不认为它可以通过反射和滥用 XAML 来完成,因为这看起来不太好给我练习。但是,为了让生活更轻松,我创建了一个简单的方法。
singleton
参数定义实例是否应该是单一的,或者每次都获得一个唯一的键。我在我的应用程序中将 MainWindow 定义为单例,而其他 ViewModel 在我的场景中不是单例。
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());
}