Реализация универсальных методов

245
31 марта 2017, 21:54

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.

Answer 1

Решение через рефлексию (не то, что хотелось бы, но ...):

Интерфейс:

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
{
.....
}
READ ALSO
Закрывается канал named pipes

Закрывается канал named pipes

Доброго дняЗадача вкратце в следующем: существует некий сервер (NamedPipeServerStream), который принимает входящие подключения клиентов (NamedPipeClientStream),...

374
Получения числа из имена контрола

Получения числа из имена контрола

привет есть кодЯ в цикле перебираю дочерние картинки грида

282
Почему не обновляется DataGridView?

Почему не обновляется DataGridView?

"Это главная форма она должна обновить дата грид но она обновляется лишь после 2 клика на кнопкуПри этом добавляется новая строка в БД но она...

359