Рефлексия. Узнать, что тип свойства наследуется от ViewModelBase - C#
Формулировка задачи:
Вот по-быстрому набросал что-то. Я погуглю ещё, почитаю, но мало ли быстрее кто поможет, не хотелось бы на это много времени тратить, если решение простое.
Цель: получить все типы, которые упомянуты в свойствах экземпляра класса ViewModelLocator, которые наследуются от ViewModelBase.
Есть ViewModelLocator, в нём свойства вью моделей. В методе Cleanup класса ViewModelLocator я хочу вызывать для каждой вью модели метод Cleanup.
Я так-то набросал такую очистку (в самом низу класса), но такой подход неудобен, нужно постоянно не забывать обновлять код метода Cleanup, а у меня WPF проекта 4 проекта (клиента) и скоро будет 5-ый, и в каждом руками менять содержимое того метода это жесть вообще:
Наследуемся от него
Вызываем Cleanup
public static class ViewModelLocatorExtentions
{
public static Type[] GetViewModelTypes(this ViewModelLocator locator)
{
var p = locator.GetType().GetProperties(BindingFlags.Public);
var types = new List<Type>(p.Length);
foreach (PropertyInfo propertyInfo in p)
{
if (propertyInfo.PropertyType == typeof(ViewModelBase))
{
types.Add(propertyInfo.PropertyType);
}
}
return types.ToArray();
}
public static void TryCleanup(this ViewModelLocator locator, ViewModelBase[] viewModels, IFileLogger logger = null)
{
}
} /// <summary>
/// This class contains static references to all the view models in the
/// application and provides an entry point for the bindings.
/// </summary>
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
Application.Current.MainWindow.Loaded += MainWindow_Loaded;
Application.Current.MainWindow.Closing += MainWindow_Closing;
LogManager.Logger.LogPath = LocalConfiguration.Instance.Folders.Logs;
DispatcherHelper.Initialize();
ProgramIdentification.Initialize(ProgramIdentifier.Dispatcher);
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<CommonCommandManager>();
SimpleIoc.Default.Register<MainViewModel>();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Main.OnWindowLoaded();
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Debug.WriteLine("Начало: MainWindow_OnClosing");
Main.OnWindowClosing();
Debug.WriteLine("Конец: MainWindow_OnClosing");
}
private void Current_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
LogManager.Logger.AppendException(e.Exception);
MessageBox.Show(e.Exception.ToString());
}
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
private static bool TryCleanup<T>() where T : ViewModelBase
{
try
{
ViewModelBase viewModel = ServiceLocator.Current.GetInstance<T>();
if (viewModel != null)
{
viewModel.Cleanup();
return true;
}
}
catch (ActivationException ex)
{
LogManager.Logger.AppendException(ex);
}
return false;
}
public static void Cleanup()
{
TryCleanup<MainViewModel>();
}
} public partial class App : Application
{
protected override void OnExit(ExitEventArgs e)
{
ViewModelLocator.Cleanup();
base.OnExit(e);
}
private void App_OnLoadCompleted(object sender, NavigationEventArgs e)
{
}
}
На свежую голову разобрался за минут 5 наверное.
public static class ViewModelLocatorExtentions
{
public static Type[] GetViewModelTypes(this ViewModelLocator locator)
{
var properties = locator.GetType().GetProperties();
var types = new List<Type>(properties.Length);
foreach (PropertyInfo propertyInfo in properties)
{
if (InheritsFromViewModelBase(propertyInfo.PropertyType))
{
types.Add(propertyInfo.PropertyType);
}
}
return types.ToArray();
}
private static bool InheritsFromViewModelBase(Type type)
{
if (type == typeof(ViewModelBase))
{
return true;
}
if (type.BaseType != typeof(object) && type.BaseType != null)
{
return InheritsFromViewModelBase(type.BaseType);
}
return false;
}
}-------------------------------------------------------------------------------------------------------------
В итоге это превратилось в это:ViewModelLocatorBase
public abstract class ViewModelLocatorBase
{
/// <summary>
/// Получить все модели представлений, которые находятся в свойствах данного экземпляра
/// </summary>
/// <returns></returns>
public ViewModelBase[] GetViewModelTypes()
{
var properties = GetType().GetProperties();
var viewModels = new List<ViewModelBase>(properties.Length);
foreach (PropertyInfo propertyInfo in properties)
{
if (InheritsFromViewModelBase(propertyInfo.PropertyType))
{
var res = propertyInfo.GetValue(this);
viewModels.Add((ViewModelBase)res);
}
}
return viewModels.ToArray();
}
/// <summary>
/// Вернут true, если переданный в качестве параметра тип наследует от <see cref="ViewModelBase"/>
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private bool InheritsFromViewModelBase(Type type)
{
if (type == typeof(ViewModelBase))
{
return true;
}
if (type.BaseType != typeof(object) && type.BaseType != null)
{
return InheritsFromViewModelBase(type.BaseType);
}
return false;
}
}ViewModelLocator
/// <summary>
/// This class contains static references to all the view models in the
/// application and provides an entry point for the bindings.
/// </summary>
public class ViewModelLocator : ViewModelLocatorBase
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public void Cleanup()
{
var viewModels = this.GetViewModelTypes();
foreach (ViewModelBase viewModel in viewModels)
{
viewModel.Cleanup();
}
}
}App
public partial class App : Application
{
protected override void OnExit(ExitEventArgs e)
{
var locator = Resources["Locator"] as ViewModelLocator;
Debug.Assert(locator != null, "locator == null");
locator.Cleanup();
base.OnExit(e);
}
}Решение задачи: «Рефлексия. Узнать, что тип свойства наследуется от ViewModelBase»
textual
Листинг программы
private static bool InheritsFromViewModelBase<T>()
{
return typeof(ViewModelBase).IsAssignableFrom(typeof(T));
}