假设我已经嵌套了类似于以下内容的通用数据类:
public class BaseRecordList<TRecord, TUserInfo>
where TRecord : BaseRecord<TUserInfo>
where TUserInfo : BaseUserInfo
{
public virtual IList<TRecord> Records { get; set; }
public virtual int Limit { get; set; }
}
public class BaseRecord<TUserInfo>
where TUserInfo : BaseUserInfo
{
public virtual DateTime CreationTime { get; set; }
public virtual TUserInfo UserInfo { get; set; }
}
public class BaseUserInfo
{
public virtual string Name { get; set; }
public virtual int Age { get; set; }
}
有两个具体的版本:
// Project 1: Requires some extra properties
public class Project1RecordList : BaseRecordList<Project1Record, Project1UserInfo> {}
public class Project1Record : BaseRecord<Project1UserInfo>
{
public Guid Version { get; set; }
}
public class Project1UserInfo : BaseUserInfo
{
public string FavouriteFood { get; set; }
}
和
// Project 2: Some properties need alternate names for JSON serialization
public class Project2RecordList : BaseRecordList<Project2Record, Project2UserInfo>
{
[JsonProperty("allRecords")]
public override IList<Project2Record> Records { get; set; }
}
public class Project2Record : BaseRecord<Project2UserInfo> {}
public class Project2UserInfo : BaseUserInfo
{
[JsonProperty("username")]
public override string Name { get; set; }
}
我很高兴有2个存储库分别返回Project1RecordList和Project2RecordList,但在我的代码中的某些时候,我发现自己需要能够在一个地方处理这两个。我认为在这一点上我需要能够将这两种类型视为
BaseRecordList<BaseRecord<BaseUserInfo>, BaseUserInfo>
因为这是满足通用约束所需的最低要求,但是尝试使用&#34;作为&#34;抛出关于无法转换的错误。
有没有办法做到这一点,甚至是一种更理智的方式来处理这种情况而没有大量的代码重复?如果它对Web应用程序产生任何影响,并且已经存在大量数据类,其中许多使用这些嵌套泛型。
答案 0 :(得分:3)
你所说的是协方差,MSDN在这里有一篇很好的文章:https://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
首先,创建一个新界面:
interface IBaseRecord<out TUserInfo>
where TUserInfo : BaseUserInfo
{
}
让BaseRecord继承新界面:
public class BaseRecord<TUserInfo> : IBaseRecord<TUserInfo>
where TUserInfo : BaseUserInfo
{
public virtual DateTime CreationTime { get; set; }
public virtual TUserInfo UserInfo { get; set; }
}
如果做得好,这应该编译:
IBaseRecord<BaseUserInfo> project1 = new Project1Record();
IBaseRecord<BaseUserInfo> project2 = new Project2Record();
要将其扩展为BaseRecordList,请创建IBaseRecordList:
interface IBaseRecordList<out TRecord, out TUserInfo>
where TRecord : IBaseRecord<TUserInfo>
where TUserInfo : BaseUserInfo
{
}
让BaseRecordList继承自:
public class BaseRecordList<TRecord, TUserInfo> : IBaseRecordList<TRecord, TUserInfo>
然后使用:
IBaseRecordList<IBaseRecord<BaseUserInfo>, BaseUserInfo> project1 = new Project1RecordList();
IBaseRecordList<IBaseRecord<BaseUserInfo>, BaseUserInfo> project2 = new Project2RecordList();
完成设置后,只需将通用的所有属性或功能添加到接口即可。