从派生类中获取特定类型

时间:2018-06-12 15:54:04

标签: c# asp.net-mvc inheritance polymorphism covariance

简短:我正在创建一个MVC应用程序,我需要在其中显示各种类型的文档,其中一些包含比其他文档更多的作者信息。

我想做什么:我的方法是拥有一个通用的"查看文档" view,以传递给它的对象的形状/类型指示的格式动态显示文档。

示例:一个简单的文档将被加载到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# doesn't support return type covarience,但希望可能有另一种方式来返回/识别派生类型,这样我就不必在视图中查询它们了。

我当前的解决方案是始终返回基类型,并为每个具体类型提供单独的视图,只需将每个对象转换为正确的类型,只查询可能不同的对象。也许这是最好的解决方案,但感觉非常不优雅。

3 个答案:

答案 0 :(得分:1)

通常你可以做一个简单的"是"校验。因此,您可以在视图中进行条件渲染,例如:

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

类型检查通常被认为是反模式,但我不确定是否有更好的方法来解决这个问题。如果您使用的是.NET Core,还可以在此处检查子类标记http://examples.aspnetcore.mvc-controls.com/InputExamples/SubClass

答案 1 :(得分:0)

可能的清除选项是在每个文档必须实现的名为GetView的接口中有一个签名。这样每种文档类型都有自己实现函数的方式,调用函数知道每个文档都有一个函数Ge​​tView。如果每个文档都有一种查看文档的独特方式,则此方法可以正常工作。但是,如果某些文档以相同的方式获取视图,那么我是否可以建议将每个View类型创建到自己的类中,并且可以将视图类型分配给每个文档。我建议调查策略模式。

第一个建议:

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();
}

答案 2 :(得分:0)

我可能会离开这里,但正如我理解你的问题...为什么不把对象中的返回类型抛出并传递给你的视图?

您可以查看所需的方法并使用反射来提取您想要的任何信息。修改它,对象类保存你想要的任何内容。

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));

现在,您可以根据MethodList

中的内容构建GetView

希望这有帮助!