Рефлексия. Узнать, что тип свойства наследуется от ViewModelBase - C#

Узнай цену своей работы

Формулировка задачи:

Вот по-быстрому набросал что-то. Я погуглю ещё, почитаю, но мало ли быстрее кто поможет, не хотелось бы на это много времени тратить, если решение простое. Цель: получить все типы, которые упомянуты в свойствах экземпляра класса ViewModelLocator, которые наследуются от ViewModelBase. Есть ViewModelLocator, в нём свойства вью моделей. В методе Cleanup класса ViewModelLocator я хочу вызывать для каждой вью модели метод 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)
        {
            
        }
    }
Я так-то набросал такую очистку (в самом низу класса), но такой подход неудобен, нужно постоянно не забывать обновлять код метода Cleanup, а у меня WPF проекта 4 проекта (клиента) и скоро будет 5-ый, и в каждом руками менять содержимое того метода это жесть вообще:
    /// <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();
            }
        }
    }
Вызываем 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));
        }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 3.818 из 5
Похожие ответы