Brief: I'm creating an MVC application in which I need to display a variety of types documents, some containing more author information than others.
简介:我正在创建一个MVC应用程序,在这个应用程序中,我需要显示各种类型的文档,其中一些文档包含比其他文档更多的作者信息。
What I wanna do: My approach is to have a generic "view document" view, which dynamically displays the document in a format dictated by the shape/type of the object passed to it.
我想做的是:我的方法是有一个通用的“视图文档”视图,它动态地显示文档的格式,由传递给它的对象的形状/类型决定。
Example: A simple document would be loaded into a SimpleDocumentViewModel, and display as such. However I'd like to load a larger type of document into an ExtendedDocumentViewModel, bringing with it additional information about both the document and the author. The view(s) would then display the appropriate data based on the object it receives.
示例:一个简单的文档将被加载到SimpleDocumentViewModel中,并以这种方式显示。但是,我希望将更大类型的文档加载到ExtendedDocumentViewModel中,并提供关于文档和作者的附加信息。然后视图将根据接收到的对象显示适当的数据。
Where I'm at now: In this vein I've created the following interfaces and classes, but I'm stuck as to how to return/identify the more specific return types in their derived classes.
我现在所处的位置:在这种情况下,我创建了以下接口和类,但是在如何返回/识别派生类中更具体的返回类型方面,我遇到了困难。
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; }
}
Question: So my question is; how best can I get the specific types from the fully implemented classes, or do I need to return the base types and query it all in the view? Or am I off my head and need to go back to the drawing board?
我的问题是;如何从完全实现的类中获得特定类型,或者是否需要返回基本类型并在视图中查询它们?还是我疯了,需要回到画板上?
Edits:
编辑:
I know that c# doesn't support return type covarience, but hoped that there may be another way of returning/identifying the derived types so that I don't have to query them all in the view.
我知道c#不支持返回类型协变,但是我希望有另一种返回/识别派生类型的方法,这样我就不必在视图中查询它们了。
My current solution would be to always return the base types, and have a separate view for each concrete type that simply casts each object to the correct type, only querying those that could differ. Perhaps this is the best solution end of, but it feels very inelegant.
我目前的解决方案是始终返回基本类型,并为每个具体类型拥有一个单独的视图,该视图只是将每个对象转换为正确的类型,只查询可能不同的类型。也许这是最好的解决方案,但它感觉非常不优雅。
3 个解决方案
#1
1
Usually you can do a simple "is" check. So you can have conditional rendering in your views, for example:
通常你可以做一个简单的“is”检查。所以你可以在视图中有条件呈现,例如:
@if(Model is ExtendedDocumentViewModel)
{
// render ExtendedDocumentViewModel html here
}
Type checking is usually considered an anti pattern, however I am not sure if there is a much better approach to this problem. If you are using .NET Core you can also check the subclass tag here http://examples.aspnetcore.mvc-controls.com/InputExamples/SubClass .
类型检查通常被认为是一种反模式,但是我不确定是否有更好的方法来解决这个问题。如果您正在使用。net Core,您还可以在这里检查子类标记http://examples.aspnetcore.mvc-controls.com/InputExamples/SubClass。
#2
0
Possible cleaner option is to just have a signature in the interface called GetView that each document has to implement. This way each document type has their own way of implementing the function and the calling function knows that each document has a function GetView. This method will work well if every document has a unique way of viewing the document. However if some documents share the same way of getting views, then may I suggest creating each View type into their own class and you can assign the views types to each document. I suggest looking into the strategy pattern.
可能的更清晰的选项是在名为GetView的接口中有一个签名,每个文档都必须实现。这样,每个文档类型都有自己的实现函数的方法,调用函数知道每个文档都有一个函数GetView。如果每个文档都有一种独特的查看文档的方式,那么这种方法就很有效。但是,如果某些文档共享获取视图的相同方式,那么我建议将每个视图类型创建到它们自己的类中,您可以为每个文档分配视图类型。我建议研究一下战略模式。
First suggestion:
第一个建议:
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();
}
Second suggestion:
第二个建议:
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();
}
#3
0
I may be way off base here, but as I understand your question... why not just throw the return types in an object and pass that to your view?
我可能说得有点离谱,但我理解你的问题……为什么不直接在对象中抛出返回类型并将其传递给视图呢?
You could look at the desired method and use reflection to pull out whatever info you want. Modify this and the object class hold whatever you want it to.
您可以查看所需的方法,并使用反射来提取您想要的任何信息。修改它,对象类保存您想要的任何东西。
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;
}
}
he object class could be something like this or modify it however you want:
对象类可以是这样的,也可以任意修改:
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;
}
}
You could call the method like this with the desired class.
您可以像这样对所需的类调用这个方法。
public static List<InternalClassObject> MethodList = new List<InternalClassObject>();
DiscoverInternalClass newDiscover= new DiscoverInternalClass();
MethodList = newDiscover.FindClassMethods(typeof(ExtendedDocumentViewModel));
Now you can have your GetView build based on what is in MethodList
现在,您可以基于MethodList中的内容构建GetView
Hope this helps!
希望这可以帮助!
#1
1
Usually you can do a simple "is" check. So you can have conditional rendering in your views, for example:
通常你可以做一个简单的“is”检查。所以你可以在视图中有条件呈现,例如:
@if(Model is ExtendedDocumentViewModel)
{
// render ExtendedDocumentViewModel html here
}
Type checking is usually considered an anti pattern, however I am not sure if there is a much better approach to this problem. If you are using .NET Core you can also check the subclass tag here http://examples.aspnetcore.mvc-controls.com/InputExamples/SubClass .
类型检查通常被认为是一种反模式,但是我不确定是否有更好的方法来解决这个问题。如果您正在使用。net Core,您还可以在这里检查子类标记http://examples.aspnetcore.mvc-controls.com/InputExamples/SubClass。
#2
0
Possible cleaner option is to just have a signature in the interface called GetView that each document has to implement. This way each document type has their own way of implementing the function and the calling function knows that each document has a function GetView. This method will work well if every document has a unique way of viewing the document. However if some documents share the same way of getting views, then may I suggest creating each View type into their own class and you can assign the views types to each document. I suggest looking into the strategy pattern.
可能的更清晰的选项是在名为GetView的接口中有一个签名,每个文档都必须实现。这样,每个文档类型都有自己的实现函数的方法,调用函数知道每个文档都有一个函数GetView。如果每个文档都有一种独特的查看文档的方式,那么这种方法就很有效。但是,如果某些文档共享获取视图的相同方式,那么我建议将每个视图类型创建到它们自己的类中,您可以为每个文档分配视图类型。我建议研究一下战略模式。
First suggestion:
第一个建议:
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();
}
Second suggestion:
第二个建议:
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();
}
#3
0
I may be way off base here, but as I understand your question... why not just throw the return types in an object and pass that to your view?
我可能说得有点离谱,但我理解你的问题……为什么不直接在对象中抛出返回类型并将其传递给视图呢?
You could look at the desired method and use reflection to pull out whatever info you want. Modify this and the object class hold whatever you want it to.
您可以查看所需的方法,并使用反射来提取您想要的任何信息。修改它,对象类保存您想要的任何东西。
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;
}
}
he object class could be something like this or modify it however you want:
对象类可以是这样的,也可以任意修改:
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;
}
}
You could call the method like this with the desired class.
您可以像这样对所需的类调用这个方法。
public static List<InternalClassObject> MethodList = new List<InternalClassObject>();
DiscoverInternalClass newDiscover= new DiscoverInternalClass();
MethodList = newDiscover.FindClassMethods(typeof(ExtendedDocumentViewModel));
Now you can have your GetView build based on what is in MethodList
现在,您可以基于MethodList中的内容构建GetView
Hope this helps!
希望这可以帮助!