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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With