将接口作为参数传递给扩展方法

时间:2008-11-28 11:36:49

标签: c# asp.net-mvc extension-methods interface

我使用扩展方法来扩展html助手来制作RSS转发器:

    public static string RSSRepeater(this HtmlHelper html, IEnumerable<IRSSable> rss)
    {
        string result="";

        foreach (IRSSable item in rss)
        {
            result += "<item>" + item.GetRSSItem().InnerXml + "</item>";
        }

        return result;
    }

因此,我将其中一个业务对象实现为IRSSable,并尝试将其传递给HTML帮助程序。但我似乎无法使它工作,我尝试过:

<%=Html.RSSRepeater(ViewData.Model.GetIssues(null, null, "") as IEnumerable<IRSSable>) %>

编译正常,但传递null

<%=Html.RSSRepeater(ViewData.Model.GetIssues(null, null, "")) %>

Intellisense抱怨无法将IEnumerable问题传递给IEnumberable IRSSable

  • 那你怎么做的?我默认调用的方法返回IEnumberable<Issue>并且问题肯定会实现IRSSAble

3 个答案:

答案 0 :(得分:14)

啊......试试:

 public static string RSSRepeater<T>(this HtmlHelper html, IEnumerable<T> rss)
     where T : IRSSable
 {
     ...
 }

然后,这应该允许您传递实现IRSSable的任何序列 - 并且泛型类型推断应该意味着您不需要指定T(作为Issue)你自己 - 编译器会处理它。

顺便说一下 - avoid concatenation here;最好StringBuilder

    StringBuilder result = new StringBuilder();

    foreach (IRSSable item in rss)
    {
        result.Append("<item>").Append(item.GetRSSItem().InnerXml).Append("</item>");
    }

    return result.ToString();

答案 1 :(得分:4)

你遇到了generic variance issues。仅仅因为某些实现IEnumerable<Issue>并不意味着它实现了IEnumerable<IRssable>。 (它将在C#4中,但我假设你没有使用它:)

你可以让你的扩展方法只需要IEnumerable并在其上调用IEnumerable.Cast<IRssable> - 这可能是最简单的方法。

编辑:Marc's suggestion可能是更好的,但我会在这里留下这个答案,因为它解释了正在发生的事情,而不仅仅是修复:)

答案 2 :(得分:0)

试试这个:

<%=Html.RSSRepeater(ViewData.Model.GetIssues(null, null, "").Cast<IRSSable>()) %>