Рефлексия. Узнать, что тип свойства наследуется от 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)); }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д