我想要一个Root
对象的集合,这些对象具有常见抽象基类的某些实现的Details
属性。
这样的事情。
public class Root<TDetails>
where TDetails : Details<TDetails>
{
public int Id { get; set; }
public TDetails Details { get; set; }
}
public abstract class Details<TSelf>
where TSelf : Details<TSelf>
{
public Root<TSelf> Root { get; set; }
}
基本上我想做类似的事情
foreach(var root in roots)
{
// do something with root properties
// some factory method...
if(root.Details.GetType() == typeof(ADetails))
{
aDetailsHandler.Handle(root.Details);
} else if (root.Details.GetType() == typeof(BDetails))
{
bDetailsHandler.Handle(root.Details);
}
}
这是对数据建模的明智方法吗?
我想出的最好的方法是这个,但看起来真的很片状
public abstract class RootBase
{
protected RootBase()
{
}
public int Id { get;set; }
public string Name { get;set; }
public string DetailsType { get; protected set; }
[NotMapped]
public abstract DetailsBase Details { get; set; }
}
public abstract class Root<TDetails> : RootBase
where TDetails : Details<TDetails>
{
public Root()
{
}
protected internal virtual TDetails DetailsInternal { get; set; }
public override DetailsBase Details { get => DetailsInternal; set => DetailsInternal = (TDetails)value; }
}
public abstract DetailsBase
{
protected DetailsBase()
{
}
public int Id { get; set; }
}
public abstract Details<TSelf> : DetailsBase
where TSelf : Details<TSelf>
{
protected DetailsBase()
{
}
public virtual Root<TSelf> Root { get; set; }
}
public class UnCoolDetails : DetailsBase
{
public const string DetailsType = "uncool";
public UnCoolDetails()
{
}
public int UnCoolLevel { get; set; }
}
public class CoolDetails : DetailsBase
{
public const string DetailsType = "cool";
public CoolDetails()
{
}
public string CoolName { get; set; }
}
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
public DbSet<RootBase> Roots { get; set; }
public DbSet<CoolDetails> CoolDetails { get; set; }
public DbSet<UnCoolDetails> UnCoolDetails { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Configure<RootBase>(b => {
b.ToTable("Roots");
b.HasKey(e => e.Id);
b.HasIndee(e => e.Name)
.IsUnique();
b.HasDiscriminator(e => e.DetailsType)
.HasValue<Person<CoolDetails>>(CoolDetails.DetailsType)
.HasValue<Person<UnCoolDetails>>(UnCoolDetails.DetailsType);
});
modelBuilder.Configure<CoolDetails>(b => {
b.ToTable("CoolDetails");
b.HasKey(e => e.Id);
b.HasOne(e => e.Root)
.WithOne(e => e.DetailsInternal)
.HasForeignKey<Root<CoolDetails>>("CoolDetailsId");
});
modelBuilder.Configure<UnCoolDetails>(b => {
b.ToTable("UnCoolDetails");
b.HasKey(e => e.Id);
b.HasOne(e => e.Root)
.WithOne(e => e.DetailsInternal)
.HasForeignKey<Root<UnCoolDetails>>("UnCoolDetailsId");
});
}
}
using(var db = new DbContext())
{
db.Roots.Add(new Root<CoolDetails>
{
Name = "Config_1",
Details = new CoolDetails
{
CoolName = "Super Cool"
}
});
db.SaveChanges();
}
using(var db = new DbContext())
{
var Roots = db.Roots.Include("DetailsInternal").First(x => x.Name == "Config_1");
//Roots.First().Details.GetType() == typeof(CoolDetails);
}