【问题标题】:prepending an anonymous type to an Enumerable<TSource>将匿名类型添加到 Enumerable<TSource>
【发布时间】:2013-01-05 16:58:29
【问题描述】:

我有下面的代码示例,我想在源参数的前面添加prepend 一些文本,这些文本可以是ISiteIFactory 类型,通过MoreLinq extension 在MVC 下拉列表中使用.该函数用于控制器操作,该操作返回序列化为 JSON 的列表,以便可以使用一些下拉级联动态加载它,否则我会在视图模型中单独执行此操作。

我想知道是否有一种方法可以在不必创建具体的 ListItem 类的情况下执行类似于下面的操作,我的示例显示了我如何使用as IListItem,但我知道这不会编译。

目前我的控制器对我的模型的任何具体类都没有概念,我有点想保持这种状态,我不确定我是否肯定需要创建一个 ListItem 的实例来完成这项工作或如果有人有其他建议?

我对泛型中的协变和逆变的知识是有限的,万一这在这里很重要?谢谢

    public interface IListItem
    {
        int Id { get; set; }
        string Name { get; set; }
    }

    public interface ISite : IListItem
    {
        int CountryId { get; set; }
    }

    public interface IFactory : IListItem
    {
        int SiteId { get; set; }
    }

    public interface IResource
    {
        int Id { get; set; }
        string Name { get; set; }
        int ContentID { get; set; }
        string Text { get; set; }
        int LanguageID { get; set; }
        string LanguageCode { get; set; }
        int Priority { get; set; }
    }

private IEnumerable<IListItem> PrependSelectionResource(IEnumerable<IListItem> source, string languageCode)
{
    if(source == null || source.Count() == 1)
        return source; // don't bother prepending the relevant resource in these cases

    try
    {
        // will throw an exception if languageCode is null or blank
        var resource = _resourceRepository.GetByNameAndLanguageCode(
            "Prompt_PleaseSelect",
            languageCode);

        if(resource == null)
            return source;

        // prepend the "Please Select" resource to the beginning of the source
        // using MoreLinq extension
        return source.Prepend(new {
            Id = 0,
            Name = resource.Text ?? ""
        } as IListItem);
    }
    catch {
        return source;
    }
}

【问题讨论】:

    标签: c# asp.net-mvc-3 linq c#-4.0


    【解决方案1】:

    很遗憾,您无能为力。您必须将实现IListItem 接口的类的具体实例传递给Prepend 方法。

    如果您担心在应用程序的其他地方公开实现,您可以在名为 PlaceholderListItem 的文件中创建一个本地实现并使用它。

    【讨论】:

    • 感谢您的回复。那对我说,我可能会受益于让我的_resourceRepository 能够以IListItem 的形式返回资源?只是它有点不合适,因为我只需要resource.Text 和我更愿意成为“”的 Id,但它可能需要为 0.. 而不是资源的记录 ID
    【解决方案2】:

    匿名类型(如new { Id = 0, Name = resource.Text ?? "" })是一个不实现任何接口的类(除了object 之外没有其他基类)。所以它不会起作用。

    如果您使用模拟框架,您可以创建一个 mock,它是一些神奇生成的实现接口的类。有时也称为存根

    但是在这种情况下,编写自己的 mock 真的很容易,当然:

    class ListItemMock : IListItem
    {
      public int Id { get; set; }
      public string Name { get; set; }
    }
    

    然后你可以用一个对象初始化器来实例化它:new ListItemMock { Id = 0, Name = resource.Text ?? "", }

    【讨论】:

    • 感谢您的澄清
    猜你喜欢
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多