该模型的类型为List,但此字典需要IEnumerable

时间:2017-01-13 21:51:56

标签: c# asp.net-mvc

在我的控制器中,我有一个简单的LINQ查询:

var results = .....ToList();

然后,我想将'结果'传递给呈现网格的视图。它需要一个模型:

@model IEnumerable<XXXX.WebSite.Areas.BrokerDashboard.Models.AccountHBSearchItem>

我不认为这会有问题,但我明白了:

  

传递到字典中的模型项的类型为'System.Collections.Generic.List,但此字典需要类型为'System.Collections.Generic.IEnumerable

的模型项

这让我感到困惑,因为从我正在阅读的所有内容来看,List<T>已经是IEnumerable<T>

根据答案here,我尝试了这个:

IEnumerable<string> eResults = results.ToList();

但是这让我感到Can implicitly convert错误。

如果我不执行.ToList(),那么results是一个IOrderedEnumerable,我明白了:

  

传递到字典中的模型项的类型为'System.Linq.OrderedEnumerable,但此字典需要类型为'System.Collections.Generic.IEnumerable

的模型项

修改

这是整个查询:

            var results = Context.GetLeadSalesAccountTransactions(accountID)
            .OrderBy(a => a.TransactionDate)
           .Select(a =>
           {
               currentTotal -= a.Debit != null ? (decimal)a.Debit : 0;
               currentTotal += a.Credit != null ? (decimal)a.Credit : 0;
               return new AccountHBSearchItem
               {
                   AccountTransactionID = a.AccountTransactionID,
                   LeadID = a.LeadSales != null ? a.LeadSales.Lead.LeadID : 0,
                   Address = a.LeadSales != null ? a.LeadSales.Lead.Address : string.Empty,
                   LotNumber = a.LeadSales != null ? a.LeadSales.Lead.LotNumber : string.Empty,
                   Type = a.AccountTransactionType.GetDisplayName(),
                   Debit = a.Debit,
                   Credit = a.Credit,
                   RemainingBalance = currentTotal,
                   TransDate = a.TransactionDate
               };
           }
                  ).OrderByDescending(i => i.TransDate).ToList();

2 个答案:

答案 0 :(得分:2)

好像您有List<T1>IEnumerable<T2>的不同类型的通用参数。从您的第二次尝试开始,我发现您使用的是IEnumerable<string>,但模型是IEnumerable<MyNamespace.MyModel>。确保通用参数相同。你可以通过

  • List<MyNamespace.MyModel>
  • IEnumerable<MyNamespace.MyModel>
  • IOrderedEnumerable<MyNamespace.MyModel>

所有这些都是合适的

答案 1 :(得分:0)

.ToList的返回类型将是<T>类型。

这意味着<T>可以是实现特定接口的任何东西,也可以是特定的具体/抽象类。这取决于使用泛型的类并返回那些<T>对象的列表。

<T>上使用接口约束意味着您可以接受<T>(或List<T>),而不知道对象<T>的实际类型,但仍然可以与之交互根据{{​​1}}必须实现的接口的特定属性或方法。

将在Razor View中使用的<T>指定为@model类型IEnumerable(您可以迭代的列表)xxx.AccountHBSearchItem。 然后,您可以从AccountHBSearchItem访问@model中可用的属性和方法。 例如:@model.AccountTransactionID, @model.LeadId

List<T>不是List<xxx.AccountHBSearchItem> - 它可能是任何东西。因此,Razor将无法访问您将在View for output上使用的属性和方法,因为它无法保证<T>对象具有适合的接口。您可以将List<Animal>传递给视图,对xxx.AccountHBSearchItem所拥有的属性的任何访问都将失败(我希望!),因为Animal不是xxx.AccountHBSearchItem }。

因此,要解决此问题,您可以在用于生成List<T>的类中声明<T>实现生成View时需要使用的接口。

假设接口需要以下属性(从您的数据中猜出);创建一个包含这些属性的接口,用于将用作<T>的所有类。

public interface IAccountHBSearchItem
{
    long AccountTransactionID { get; set; }
    long LeadID { get; set; }
    string Address { get; set; }
    string LotNumber { get; set; }
    string Type { get; set; }
    bool Debit { get; set; }
    bool Credit { get; set; }
    decimal RemainingBalance { get; set; }
    DateTime TransDate { get; set; }
}

现在指定不同的类实现此接口:

public class AccountSearchAAA<T> where T : IAccountHBSearchItem
{
    // Rest of implementation
    public List<T> GetAll()
    {
        // return list of AccountSearchAAA objects here
    }
}

public class AccountSearchBBB<T> where T : IAccountHBSearchItem
{
    // Rest of implementation
    public List<T> GetAll()
    {
        // return list of AccountSearchBBB objects here
    }
}

然后,您可以将@model更改为使用IEnumerable<xxx.IAccountHBSearchItem>(界面)。

现在,您可以生成不同帐户类型的搜索结果,只要它们实现此界面,然后在同一个视图中使用它们。

现在可以通过界面访问可用的属性和方法了。