简介:我正在创建一个MVC应用程序,我需要在其中显示各种类型的文档,其中一些文档比其他文档包含更多的作者信息。
我想做的:我的方法是有一个通用的"视图文档"视图,它以传递给它的对象的形状/类型决定的格式动态显示文档。
示例:一个简单的文档将被加载到 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# 不支持返回类型协变,但希望可能有另一种返回/标识派生类型的方法,这样我就不必在视图中查询它们。
我当前的解决方案是始终返回基类型,并为每个具体类型提供一个单独的视图,该视图只是将每个对象强制转换为正确的类型,仅查询可能不同的对象。也许这是最好的解决方案结束,但它感觉非常不优雅。
通常你可以做一个简单的"is"检查。因此,您可以在视图中进行条件呈现,例如:
@if(Model is ExtendedDocumentViewModel)
{
// render ExtendedDocumentViewModel html here
}
类型检查通常被认为是一种反模式,但是我不确定是否有更好的方法来解决这个问题。如果您使用的是.NET Core,您还可以在此处检查子类标记 http://examples.aspnetcore.mvc-controls.com/InputExamples/SubClass。
可能的更干净的选择是在名为 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();
}
我可能在这里离基地很远,但据我了解你的问题......为什么不直接将返回类型抛到对象中并将其传递给您的视图?
您可以查看所需的方法并使用反射来提取所需的任何信息。修改它,对象类将保存您想要的任何内容。
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
希望这有帮助!