using System.Collections.Generic;
public int Id { get; set; }
public class InfoData<TInfo> : Data
public TInfo Info { get; set; }
public abstract class InfoBase
public int Id { get; set; }
public interface IRelated
IList<InfoBase> Related {get; set;}
public class ExtraInfo : InfoBase, IRelated
public string Extras { get; set; }
public IList<InfoBase> Related { get; set; }
public class OtherInfo : InfoBase, IRelated
public DateTime Created { get; set; }
public IList<InfoBase> Related { get; set; }
public static void Show<TData>(string descriptor, int id, int? related = null)
Console.WriteLine("{0}: id={1} related={2}", descriptor, id, related);
public static TData Add<TData>(TData data)
Show<TData>("Add<TData>", data.Id);
public static TData Add<TData, TInfo>(TData data)
where TData: InfoData<TInfo>
where TInfo: InfoBase, IRelated
Show<TData>("Add<TData,TInfo>", data.Id, data.Info.Related[0].Id);
public static void Main(string[] args) {
Add(new InfoData<ExtraInfo> {
Related = new List<InfoBase> {
Add<InfoData<ExtraInfo>, ExtraInfo>(new InfoData<ExtraInfo> {
Related = new List<InfoBase> {
Add<InfoData<OtherInfo>, OtherInfo>(new InfoData<OtherInfo> {
Related = new List<InfoBase> {