Получить конкретный тип из производного класса - PullRequest
0 голосов
/ 12 июня 2018

Краткое описание : я создаю приложение MVC, в котором мне нужно отобразить документы различных типов, некоторые из которых содержат больше информации об авторе, чем другие.

Что я хочуdo : Мой подход заключается в том, чтобы иметь общее представление «Просмотр документа», которое динамически отображает документ в формате, определяемом формой / типом переданного ему объекта.

Пример : простой документ будет загружен в SimpleDocumentViewModel и отображен как таковой.Однако я хотел бы загрузить документ большего типа в ExtendedDocumentViewModel, предоставив дополнительную информацию как о документе, так и об авторе.Представления будут отображать соответствующие данные на основе получаемого объекта.

Где я сейчас нахожусь : В этом ключе я создал следующие интерфейсы и классы:но я застрял в том, как вернуть / определить более конкретные типы возврата в их производных классах.

abstract class BaseDocumentViewModel : DocumentViewModel, IDocumentViewModel
{
    public int DocumentId { get; set; }
    public string Body { get; set; }
    public IAuthorViewModel Author { get; set; }
}

class SimpleDocumentViewModel : BaseDocumentViewModel
{
}

class ExtendedDocumentViewModel : BaseDocumentViewModel
{
    public new IAuthorExtendedViewModel Author { get; set; }
}

interface IAuthorViewModel
{
    int PersonId { get; set; }
    string Name { get; set; }
}

interface IAuthorExtendedViewModel : IAuthorViewModel
{
    int ExtraData { get; set; }
    int MoreExtraData { get; set; }
}

Вопрос : Итак, мой вопрос;Как лучше всего получить конкретные типы из полностью реализованных классов, или мне нужно вернуть базовые типы и запросить все это в представлении?Или я не в себе и мне нужно вернуться к чертежной доске?

Правки:

Я знаю, что c # не поддерживает ковариацию типа возврата, но надеялся, что может быть другой способ возврата / идентификации производных типов, так что мне не придется запрашивать их все в представлении.

Моим текущим решением было бы всегда возвращать базутипы, и имеют отдельное представление для каждого конкретного типа, который просто приводит каждый объект к правильному типу, запрашивая только те, которые могут отличаться.Возможно, это лучшее решение конца, но оно выглядит очень не элегантно.

Ответы [ 3 ]

0 голосов
/ 12 июня 2018

Возможная более чистая опция - просто иметь подпись в интерфейсе GetView, которую должен реализовать каждый документ.Таким образом, каждый тип документа имеет свой собственный способ реализации функции, и вызывающая функция знает, что у каждого документа есть функция GetView.Этот метод будет хорошо работать, если каждый документ имеет уникальный способ просмотра документа.Однако если некоторые документы используют один и тот же способ получения представлений, я могу предложить создать каждый тип представления в своем собственном классе, и вы можете назначить типы представлений каждому документу.Я предлагаю изучить шаблон стратегии.

Первое предложение:

class SimpleDocumentViewModel : IAuthorViewModel
{
      view GetView()
      {
          ... do document specific stuff
          ... return view
      }
}

class ExtendedDocumentViewModel : IAuthorViewModel
{
      int ExtraData { get; set; }
      int MoreExtraData { get; set; }

      view GetView()
      {
          ... do document specific stuff
          ... return view
      }
}

interface IAuthorViewModel
{
    view GetView();
}

Второе предложение:

class SimpleDocumentViewModel : IAuthorViewModel
{
      public viewType1 view {get;set;}

      public SimpleDocumentViewModel(viewType1 viewIn,etc...)
      {
          view = viewIn;
      } 
      view GetView()
      {
          return view.GetView();
      }
}

class ExtendedDocumentViewModel : IAuthorViewModel
{
      int ExtraData { get; set; }
      int MoreExtraData { get; set; }
      public viewType2 view {get;set;}

      public ExtendedDocumentViewModel(viewType2 viewIn,etc...)
      {
          view = viewIn;
      } 
      view GetView()
      {
          return view.GetView(ExtraData,MoreExtraData);
      }
}

interface IAuthorViewModel
{
    view GetView();
}
0 голосов
/ 12 июня 2018

Я могу быть далеко от основания здесь, но, как я понимаю ваш вопрос ... почему бы просто не бросить возвращаемые типы в объект и передать это на ваш взгляд?

Вы можете посмотреть на нужный методи используйте рефлексию, чтобы извлечь любую информацию, которую вы хотите.Измените это, и класс объекта будет содержать все, что вы хотите.

public class DiscoverInternalClass
{
    public List<InternalClassObject> FindClassMethods(Type type)
    {
        List<InternalClassObject> MethodList = new List<InternalClassObject>();

        MethodInfo[] methodInfo = type.GetMethods();

        foreach (MethodInfo m in methodInfo)
        {
            List<string> propTypeList = new List<string>();
            List<string> propNameList = new List<string>();

            string returntype = m.ReturnType.ToString();

            foreach (var x in m.GetParameters())
            {
                propTypeList.Add(x.ParameterType.Name);
                propNameList.Add(x.Name);

            }
            InternalClassObject ICO = new InternalClassObject(c.Name, propNameList, propTypeList);
            MethodList.Add(ICO);
        }
        return MethodList;
    }
}

он может быть чем-то вроде этого класса объекта или изменить его так, как вы хотите:

public class InternalClassObject
{
    public string Name { get; set; }
    public List<string> ParameterNameList { get; set; }
    public List<string> ParameterList { get; set; }

    public InternalClassObject(string iName,List<string> iParameterNameList, List<string> iParameterList)
    {
        Name = iName;
        ParameterNameList = iParameterNameList;
        ParameterList = iParameterList;
    }
}

Вы можете вызватьметод, подобный этому, с нужным классом.

public static List<InternalClassObject> MethodList = new List<InternalClassObject>();

DiscoverInternalClass newDiscover= new DiscoverInternalClass();
MethodList = newDiscover.FindClassMethods(typeof(ExtendedDocumentViewModel));

Теперь вы можете получить свою сборку GetView, основанную на том, что находится в MethodList

Надеюсь, это поможет!

0 голосов
/ 12 июня 2018

Обычно вы можете сделать простую проверку "is".Таким образом, у вас может быть условный рендеринг в ваших представлениях, например:

@if(Model is ExtendedDocumentViewModel)
{
  // render ExtendedDocumentViewModel html here
}

Проверка типов обычно считается антишаблоном, однако я не уверен, существует ли гораздо лучший подход к этой проблеме.Если вы используете .NET Core, вы также можете проверить тег подкласса здесь http://examples.aspnetcore.mvc -controls.com / InputExamples / SubClass .

...