C# WindowsForms Что-то запутался в универсальных методах и пр..
Основная цель - обращение к методу объекта через интерфейс (Interface).
Описание: объект должен иметь метод VIEW с возможностью принимать в качестве параметра разные "классы".
Что пробовал делать: объявляю в интерфейсе IAppObject метод void View<T>(T Model) where T : class. Казалось бы так и должно быть, но мне надо в дальнейшем в наследнике этого интерфейса реализовать несколько методов VIEW в зависимости от того, какой класс передан в качестве <T>. Т.е. если я передаю туда например MyClassA - то метод View должен делать одно, если передаю MyClassB - то метод View должен делать другое. Обычно такое реализовывают через перегрузку методов, но интерфейс применяется к разным классам у которых должен быть метод View и не каждый из них должен принимать MyClassA, соответственно перегрузку методов в Интерфейсе делать нельзя - это создаст кучу ненужных реализаций в наследнике.
Пробовал делать в наследнике через where T: MyClassA, но требует конкретную реализацию условия как в интерфейсе.
Пример интерфейса:
public interface IAppObject : IDisposable
{
/// <summary>
/// Просмотр видимой части объекта "по умолчанию".
/// </summary>
void View();
/// <summary>
/// Просмотр видимой части объекта в зависимости от переданной модели.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="Model"></param>
void View<T>(T Model) where T : class;
/// <summary>
/// Событие - уничтожение текущего объекта.
/// </summary>
event EventHandler EventRemoveObject;
}
Пример метода View реализованного в классе:
/// <summary>
/// Показать визуальную часть от модели.
/// </summary>
void IAppObject.View<T>(T Model)
{
UserSessionModel us = Model as UserSessionModel;
this.View(us);
}
/// <summary>
/// Показать визуальную часть от модели.
/// </summary>
public void View<T>(T Model) where T : UserSessionModel
{
}
Как видно из примера реализации метода View в наследнике интерфейса, для того, чтобы вызвать метод перегрузки, понадобится определять какой тип имеет переданный параметр T - т.е. сотворять кучу if,swith и прочей чепухи.. Просто передать в качестве параметра Model не получится, т.к. будет ругаться на отсутствие явного преобразования к UserSessionModel.
Вопрос: как можно описать в интерфейсе (Interface) метод (возможно универсальный), но реализацию в наследнике выполнить перегруженным методом ? PS: использовать наследование класса (простого/абстрактного) не хотелось бы, интересует именно через Interface.
Решение через рефлексию (не то, что хотелось бы, но ...):
Интерфейс:
public interface IAppObject : IDisposable
{
void View();
void View<T>(T Model) where T : AModel;
event EventHandler EventRemoveObject;
}
Пришлось использовать 1 общий класс для всех моделей, чтобы "централизовать" условие для ограничения в универсальном методе.
Реализация "перегрузки" (термин скорее неверный, но действие похожее) универсального метода в классе с использованием рефлексии:
void IAppObject.View()
{
this.RemoveObject(null, null);
}
// Данный метод описан возможно неверно, т.к на момент составления
// ответа реализацию этого метода для удобства пришлось сделать через абстрактный класс
public IAppObject.View<T>(T Model)
{
Type th = this.GetType();
MethodInfo mi = th.GetMethod("View", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { Model.GetType() }, null);
mi?.Invoke(this, new object[] { Model });
}
// Метод класса используемый для перегрузки.
public void View(UserSessionModel Model)
{
}
Пример обращения:
IAppObject StartObject = new AppObject();
StartObject.View(new UserSessionModel());
При этом, класс UserSessionModel имеет обязательное наследование AModel, для выполнения условия ограничения параметра T в универсального метода:
public class UserSessionModel : AModel
{
.....
}
Сборка персонального компьютера от Artline: умный выбор для современных пользователей