如何根据字段值自动创建具体类

本文关键字:创建 何根 字段 | 更新日期: 2023-09-27 17:55:36

考虑这个例子:

数据库(类似于 Stackoverflow)有一个表,其中的问题和答案位于同一个表中,可通过PostType字段区分。 我想找回最新帖子的列表,无论是问题还是答案。

由于问题和答案共享共同的属性,因此这两个类都继承自抽象类ContentBase。它们只添加几个与每种类型相关的附加字段。

如何获取投射到IList<ContentBase>的内容项列表,而单个项具有基于条件字段的具体类型QuestionAnswer

public abstract class ContentBase
{
    public int Id { get; set; }
    public string Title { get; set; }
    public User Author { get; set; }
    public abstract ContentType Type { get; }
    ...
}
public class Question : ContentBase
{
    public override ContentType Type
    {
        get { return ContentType.Question; }
    }
    ...
}
public class Answer: ContentBase
{
    public override ContentType Type
    {
        get { return ContentType.Answer; }
    }
    ...
}

然后,我的存储库将有一个调用:

IList<ContentBase> result = db.GetLatest();

我正在使用PetaPoco/NPoco,但我想如果使用Dapper,也会出现同样的问题。

问题

如何指示 DAL 根据特定字段的值实例化正确的具体类型(在这种情况下ContentType)?

解释

我应该按照这些思路做一些事情:

db.Fetch<ContentBase, User>(...)

但我不能,因为ContentBase是一个抽象类。如果我将此行更改为:

db.Fetch<dynamic, User>(...)

它仍然不起作用,因为我从 NPoco 收到一个InvalidOperationException,说无法自动加入用户

我想做到这一点的唯一方法是创建一个从PocoData继承的新类,并提供我自己的GetFactory委托实现。我认为。我认为没有任何其他扩展点可以实例化具体的 POCO,我不确定我是否应该这样做以及如何这样做,因为我正在处理抽象祖先类。

如何根据字段值自动创建具体类

不确定我是否正确理解这一点。

  1. 你能通过拥有一个基类来解决这个问题,该基类获取枚举的整数值,将问答加载到一个集合中,然后在内存中将其拆分为 Q'a 和 A?这似乎简单得多。

  2. 也许分开问答:

    var s = @"select q.Id, q.Title, q.ContentType as Type , q.Author as Name from QA q where q.ContentType = @0;";
    var q = db.Fetch<Question,User>(s,1);
    var a = db.Fetch<Answer, User>(s,2);
    
  3. 你能通过使用多个结果集来解决这个问题吗?

    var sql  = @"select * from QA where contenttype = 1; select * from qa where
    contenttype  =1;";
    var com = db.FetchMultiple<Question,Answer>(sql);
    com.Dump();
    

注意:我的数据库表使用nvarchar进行User,并在您的底座中string用于User

ContentType创建了一个枚举

void Main()
{
    var sql  = @"select * from QA where contenttype = 1; select * from QA where contenttype  = 2;";
    var com = db.FetchMultiple<Question, Answer>(sql);
    com.Dump();
}

此处使用的其他方法和类型

public enum ContentType
{
    Question,
    Answer
}
public abstract class ContentBase
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public abstract ContentType Type { get; }
}
public class Question : ContentBase
{
    public override ContentType Type
    {
        get { return ContentType.Question; }
    }
}
public class Answer: ContentBase
{
    public override ContentType Type
    {
        get { return ContentType.Answer; }
    }
}