我有以下代码:
public class EntitySchema
{
}
public class ContactEntitySchema : EntitySchema
{
}
public class ProductEntitySchema : EntitySchema
{
}
public class Entity<TEntitySchema>
where TEntitySchema : EntitySchema
{
public string Id { get; set; }
}
public class Contact : Entity<ContactEntitySchema>
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Product : Entity<ProductEntitySchema>
{
public string Name { get; set; }
}
public class ViewBase<TEntity>
where TEntity : Entity<EntitySchema>
{
public TEntity Entity { get; set; }
}
public class ContactView : ViewBase<Contact>
{
public ContactView()
{
}
}
public class ProductView : ViewBase<Entity<EntitySchema>>
{
public ProductView()
{
}
}
我为ContactView类收到以下错误:
错误1类型
'Generics.Contact'
不能用作泛型类型或方法'TEntity'
中的类型参数'Generics.ViewBase<TEntity>'
。没有从'Generics.Contact'
到'Generics.Entity<Generics.EntitySchema>'
的隐式引用转换。
然后我定义了ProductView有点不同,它成功编译。但是,在ProductView中,如果我想使用某些特定于产品的字段,我应该将Entity属性显式地转换为Product。有没有办法重新编写ContactView的声明,所以我可以指定实际的实体类型(在这种特殊情况下 - 联系)?
答案 0 :(得分:1)
您遇到的问题是public class Entity<TEntitySchema>
是generically invariant。这意味着即使你知道ContactEntitySchema : EntitySchema
并不意味着编译器可以在ContactEntitySchema
中替换EntitySchema
ViewBase
的泛型类型定义1}}。
(要明白为什么会这样,请考虑如果您尝试将List<Cat>
视为List<Animal>
会发生什么,反之亦然。)
我可能误解了您的问题,但首先您可以尝试直接在视图的类型参数中指定架构类型,使用类型约束来确保TEntity
和{{1}之间的关系保留?: -
TSchema
或者,您可以将public class ViewBase<TEntity, TSchema>
where TEntity : Entity<TSchema>
where TSchema : EntitySchema
{
public TEntity Entity { get; set; }
}
public class ContactView : ViewBase<Contact, ContactEntitySchema>
{
public ContactView()
{
}
}
public class ProductView : ViewBase<Entity<EntitySchema>, EntitySchema>
{
public ProductView()
{
}
}
更改为界面: -
Entity
允许您指定public interface IEntity<out TEntitySchema>
where TEntitySchema : EntitySchema
{
string Id { get; set; }
}
public class Contact : IEntity<ContactEntitySchema>
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
// etc
泛型类型参数是协变的(使用TEntitySchema
关键字)。
任何一种解决方案都应该允许您在视图对象中以强类型方式访问out
。