2014-02-18 24 views
2

是否可以将接口指定为不同接口的通用集合属性的类型,然后使用特定类实现它?这里是什么,我试图做一个例子:ICollection与另一个接口的接口类型为

public interface IMembershipPrincipal 
{ 
    int ID { get; set; } 
    string UserName { get; set; } 
    ICollection<IEmail> Emails { get; set; } 
} 

public interface IEmail 
{ 
    string Address { get; set; } 
    int UserID { get; set; } 
} 

,并确定在另一个项目的实际类:

public class User : IMembershipPrincipal 
{ 
    [Key] 
    public int ID { get; set; } 
    public string UserName { get; set; } 
    public virtual ICollection<Email> Emails { get; set; } 
} 

public class Email : IEmail 
{ 
    [Key] 
    public string Address { get; set; } 
    public int UserID { get; set; } 
} 

在IMembershipPrincipal我只能访问到IEmail定义,但我会喜欢使用电子邮件而不是IEmail实现ICollection。我目前收到一条错误消息:

错误1'用户'未实现接口成员'IMembershipPrincipal.Emails'。 “User.Emails”无法实现“IMembershipPrincipal.Emails”,因为它没有System.Collections.Generic.ICollection'.`

的”匹配的返回类型我怎样才能改变我的IMembershipPrincipal定义,使其能用ICollection<Email>实施?

为了清楚起见,我知道将虚拟集合实现为ICollection<IEmail>将使代码生成,但它会破坏我在Entity框架中的路径,因此我不能执行类似MyUser.Emails.Where(...)的操作。

+0

你不能。 'ICollection '不是协变的,所以您不能将'Email'实例添加到'ICollection '。这是设计。 – MarcinJuraszek

+0

我可以使用协变的ICollection以外的东西吗? – Dusty

+1

不可以。没有办法获得允许“添加”操作的协变集合。 – MarcinJuraszek

回答

2

正如其他人所提到的,协方差使您无法使用示例中的代码。但是,您可以使用泛型类型和约束来获得所需的效果。

public interface IMembershipPrincipal<T> where T:IEmail 
{ 
    int ID { get; set; } 
    string UserName { get; set; } 
    ICollection<T> Emails { get; set; } 
} 

public interface IEmail 
{ 
    string Address { get; set; } 
    int UserID { get; set; } 
} 

public class User : IMembershipPrincipal<Email> 
{ 
    [Key] 
    public int ID { get; set; } 
    public string UserName { get; set; } 
    public virtual ICollection<Email> Emails { get; set; } 
} 

public class Email : IEmail 
{ 
    [Key] 
    public string Address { get; set; } 
    public int UserID { get; set; } 
} 
+0

像魅力一样工作。泛型类型正是我所需要的。谢谢! – Dusty