5

想象一下,我有一个实现名为 ISummary 的接口的对象列表,此列表中的对象可能具有其他属性,即。

public interface ISummary {
  Guid Id {get;set;}
  string Title {get;set;}
  DateTime Created {get;set;}
}

public class GigSummary: ISummary {
 Guid Id {get;set;}
 string Title {get;set;}
 DateTime Created {get;set;}
 string VenueName {get;set}
 string Band {get;set;}
}

public class NewsSummary: ISummary {
 Guid Id {get;set;}
 string Title {get;set;}
 DateTime Created {get;set;}
 string Author{get;set}
}

我现在将这个 Gigs 和 News Summary 对象列表(作为 ISummary 列表)作为模型传递给视图。

我想为列表中包含的每种类型使用不同的部分来呈现此列表。

我怎么能这样做是 ASP.NET MVC?

4

5 回答 5

8

我能想到的最明显的方法是执行以下操作:

    foreach(ISummary summ in listOfISummary) {
    Html.RenderPartial(String.Fomat("~/Views/Shared/{0}Renderer.ascx", summ.GetType.ToString()), summ, ViewData);%>
}

并使用命名约定创建强类型视图,例如 NewsSummaryRenderer.ascx。

我希望您可以将其移至辅助方法,但我会通过扩展方法将其添加到现有辅助方法之一,而不是像之前建议的那样将其放入代码中。

于 2009-06-05T13:32:37.130 回答
0

您可以在视图的代码隐藏中放置一个辅助方法,然后执行以下操作:

Type modelType = this.Model.GetType();

if (modelType == typeof(NewsSummary))  this.RenderPartial("newspartial", this.Model as NewsSummary);
else if (modelType == typeof(GigSummary)) this.RenderPartial("gigpartial", this.Model as GigSummary);
于 2009-06-05T13:27:38.823 回答
0

刘易斯走在正确的轨道上。我会采取稍微不同的策略——让两个“小部件”都从一个公共基类扩展而来,该基类提供有关所涉及的视图名称的信息。然后将扩展方法添加到您的页面类以“渲染小部件”,这可以获得适当的视图。

查看 Kona ASP.NET MVC 示例应用程序以获取此概念的工作示例。

于 2009-06-05T13:36:23.283 回答
0

我会创建一个这样做的 HtmlHelper 扩展。下面是一些看起来非常像 c# 的伪代码,实际上可能可以工作:

public static void TemplatedList<T>(this HtmlHelper me, IEnumerable<T> items, 
IDictionary<Type, Action<T>> templates)
{
  foreach(var item in items)
  {
    var template = templates[item.GetType()];
    if(template != null) template(item);
  }
}

我会这样使用它:

<% HtmlHelper.TemplatedList(ViewData.Model, new Dictionary
  {
    {typeof(GigSummary), x => %>

<div class="gigSummary">
SUP!  GIG ANNOUNCEMENT FOR <%= x.Band %>!!

What:  <%= x.Title %>
When: <%= x.Created %>
Who: <%= x.Author %>
</div>

    <%}
  // add more type/template pairs here
  }); %>
于 2009-06-05T13:37:59.037 回答
0

这是一个简单的扩展方法,您可以创建它来仅提取您需要的类型:

public static class Extensions
{
    public static IEnumerable<U> ExtractOfType<U, T>(this IEnumerable<T> list)
        where T : class
        where U : class
    {
        foreach (var item in list)
        {
            if (typeof(U).IsAssignableFrom(item.GetType()))
            {
                yield return item as U;
            }
        }
    }
}

测试:

public interface IBaseInterface
{
    string Foo { get; }
}

public interface IChildInterface : IBaseInterface
{
    string Foo2 { get; }
}

public interface IOtherChildIntreface : IBaseInterface
{
    string OtherFoo { get; }
}

public class BaseImplementation : IBaseInterface
{
    public string Foo { get { return "Foo"; } }
}

public class ChildImplementation : IChildInterface
{
    public string Foo2 { get { return "Foo2"; } }
    public string Foo { get { return "Foo"; } }
}

public class OtherChildImplementation : IOtherChildIntreface
{
    public string OtherFoo { get { return "OtherFoo"; } }
    public string Foo { get { return "Foo"; } }
}

……

        List<IBaseInterface> b = new List<IBaseInterface>();
        b.Add(new BaseImplementation());
        b.Add(new ChildImplementation());
        b.Add(new OtherChildImplementation());
        b.Add(new OtherChildImplementation());


        foreach (var s in b.ExtractOfType<IOtherChildIntreface, IBaseInterface>())
        {
            Console.WriteLine(s.GetType().Name);
        }

这将获取列表中您要查找的派生类型的所有项目。因此,在您的控制器中,将整个列表传递给视图。然后,让部分视图采用部分需要的类型的 IEnumerable,并在您的主视图中调用此扩展方法并将结果传递给这些单独的部分视图。

于 2009-06-05T13:40:01.217 回答