繁体   English   中英

将混凝土类型转换为嵌套的通用基本类型

[英]Cast concrete type to nested generic base type

假设我嵌套了类似于以下内容的通用数据类:

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; }
}

有2个具体的版本,如下所示:

// 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; }
}

然后,我很高兴拥有两个分别返回Project1RecordList和Project2RecordList的存储库,但是在我的代码中的某个时候,我发现自己需要能够在一个地方处理这两个存储库。 我认为这时我需要将这两种类型都视为

BaseRecordList<BaseRecord<BaseUserInfo>, BaseUserInfo>

因为这是满足一般约束的最低要求,但是尝试强制转换或使用“ as”会引发有关无法转换的错误。

有没有办法做到这一点,或者甚至在没有大量代码重复的情况下更合理的方式来处理这种情况? 如果有什么不同,这是针对Web应用程序的,已经有大量的数据类,其中许多使用这些嵌套的泛型。

您正在谈论的是所谓的协方差,MSDN在此提供了一篇很棒的文章: https : //msdn.microsoft.com/zh-cn/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();

完成设置后,只需将需要通用使用的任何属性或功能添加到接口即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM