Implementing an ICollection<ISomething> with a concrete type to satisfy Entity Framework

c#, entity-framework, entity-framework-6, interface

Solution

To let the covariance/contravariance work I define navigation properties as enumerables in my interfaces:

public interface IFoo
{
    IEnumerable<IBar> Bars { get; }
}

public class Foo : IFoo
{
    public virtual ICollection<Bar> Bars { get; set; }
    IEnumerable<IBar> IFoo.Bars
    {
       return this.Bars;
    } 
}

This is still enough for EF LINQ queries built on interface types.

Problem

So, this is kind of an obtuse question, but let me see if I can lay it out relatively simply. Lets say I have the following interface: ``` public interface IFoo { ICollection<IBar> Bars { get; set; } } ``` Which I then implement with: ``` public class Foo : IFoo { public virtual ICollection<IBar> Bars { get; set; } } ``` Only Entity Framework can't work with interfaces, so it pretty much completely ignores this navigation property. In order to get EF to recognize it, I need to change it to: ``` public virtual ICollection<Bar> Bars { get; set; } ``` Where `Bar` would be my implementation of `IBar`. Only, that fails to implement the interface, which wants `IBar` not `Bar`. Now, consider a slightly different scenario, where I've just got a basic foreign key: ``` public interface IFoo { IBar Bar { get; set; } } public class Foo : IFoo { public virtual IBar Bar { get; set; } } ``` Same issue, but here, I can solve it by adding: ``` public class Foo : IFoo { public virtual Bar Bar { get; set; } IBar IFoo.Bar { get { return Bar; } set { Bar = (Bar)value; } } } ``` EF is happy because it has a concrete type and the interface is happy because it has an implementation with `IBar`. The problem is that I can't figure out how to apply the same logic with an `ICollection<IBar>` because `(ICollection<Bar>)value` raises an exception saying "Cannot implicitly convert type `ICollection<Bar>` to `ICollection<IBar>`". How should I properly make the cast? UPDATE So, I wasn't paying close enough attention to where the error was being generated. It was actually complaining about the `get { return Bars; }` bit. I was able to get rid of the error by changing it to: ``` public class Foo : IFoo { public virtual ICollection<Bar> Bars { get; set; } ICollection<IBar> IFoo.Bars { get { return (ICollection<IBar>)Enumeration.Cast<IBar>(Bars); } set { Bars = (ICollection<Bar>)value; } } } ``` That seems a little hokey to me though, like I'm only masking the error and creating a little time bomb for myself. I'd appreciate any thoughts or alternate solutions.

Original source