如果模型实现IEnumerable <booking>接口,为什么不能进行强制转换?

时间:2019-02-07 09:47:17

标签: c# .net entity-framework

我想知道为什么不能在ViewModel的构造函数中进行强制转换:

public BookingsViewModel()
{
    IEnumerable<Booking> bookingsDB = repository.GetBookings();
    model = bookingsDB; //exception
}

这使我异常:

  

无法将类型System.Collections.Generic.IEnumerable<Library2.Models.Booking>隐式转换为Library2.Models.Bookings。存在显式转换(您是否缺少演员表?)

GetBookings()如下所示:

public IEnumerable<Booking> GetBookings()
{
    var bookings = context.Bookings.
            Include(i => i.Book).
            Include(i => i.Reader).
            AsEnumerable().
            ToList();
    return bookings;
}

Bookings这样的模型:

public class Bookings : IEnumerable<Booking>
{
    private List<Booking> bookingList = new List<Booking>();
    public void AddBooking(Booking booking)
    {
        bookingList.Add(booking);
    }
    public bool DeleteBooking(Booking booking)
    {
        return bookingList.Remove(booking);
    }
    public int BookingList
    {
        get
        {
            return bookingList.Count;
        }
    }
    public Booking this[int index]
    {
        get
        {
            return bookingList[index];
        }
    }
    public IEnumerator<Booking> GetEnumerator()
    {
        return bookingList.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

如果Bookings实现IEnumerable<Booking>,问题出在哪里?如何解决问题?

3 个答案:

答案 0 :(得分:2)

几乎不需要为用户代码中的集合实现IEnumerable<T>。另请参见Why not inherit from List<T>?。这样做可能是您要解决的问题的错误方法。

现在您有一个变量Bookings model,其中Bookings : IEnumerable<Booking>,并且想为该变量分配一个IEnumerable<Booking>-您不能。就像不能将Animal实例分配给Dog变量一样,狗是动物,但并非每只动物都是狗。

model的类型更改为IEnumerable<Booking>,或者完全更改您的方法。

答案 1 :(得分:0)

即使Bookings != IEnumerable<Booking>实现了Bookings,也无法像这样IEnumerable<Booking>进行广播。

您可以这样想,我的汽车有一个IDoors界面,我的卡车有一个IDoors界面。但是,称它们相同是没有意义的,它们只是共享相同的门合同。无论我是否尝试使用隐式强制转换,我都无法将卡车变成汽车,我所能做的就是说它们在车门上有相似之处

答案 2 :(得分:0)

问题出在变量model

private Bookings model;

尽管类模型实现了IEnumerable<Booking>,但它不是repository.GetBookings()返回的对象的同一类(是其父类)。

将此与以下内容进行比较:

class Person {...}
class Male : Person {...}
class Female : Person {...}

Person p = new Male();
Female f = p;

您不能仅将对象分配给不相关类的对象。

您需要编写一个转换器,将任何顺序的Bookings转换为Bookings类的对象。最简单的方法是添加一个构造函数:

public Bookings(IEnumerable<Booking> bookings)
{
    this.bookingList = bookings.ToList();
}

注意:bookingList是一个新列表,包含与预订相同的元素。如果您将预订添加到原始列表,则不会将其添加到Bookings对象中,反之亦然。

其他可能的改进:很显然,您计划将预订内部存储在  清单。为什么不实施IList<Booking>。您只需付出很少的努力即可添加很多功能

class Bookings : IList<Booking>, IReadonlyList<Booking>, IReadonlyCollection<Booking>
{
    public Bookings()
    {
        this.bookings = new List<Booking>();
    }

    public Bookings(IEnumerable<Booking> bookings)
    {
        this.bookings = bookings.ToList();
    }

    private readonly IList<Booking> bookings;

    public int Count => this.booking.Count;
    public void Add(Booking booking) {this.booking.Add(booking);}
    public void Remove(Booking booking) {this.booking.Remove(booking);}
    public IEnumerator<Booking> GetEnumerator() {return this.booking.GetEnumerator();}
    etc.
}

注意:在Visual Studio中,如果右键单击IList<Bookin>,然后选择“快速操作和重构”,则所有功能将立即实现。您甚至可以说所有这些功能都应使用this.booking