2

对于工作,我们有特定类型的记录,但每个项目都有自己的实现。列等不同,但大体流程是一样的(记录分为批次、批次分配、批次完成、批次退回、批次发出等)。许多列也很常见,但有时名称会发生​​变化(一个中的 BatchId 与另一个中的 Id。[Column("name")] 解决了这个问题)。

目前,这就是我使用接口中给出的通用组件实现批处理分配功能的方法:

public interface IAssignment
{
   // properties
   ...
   // methods
   T GetAssignmentRecord<T>(int UserId, int BatchId) where T : IAssignment;
   List<T> GetAssignmentRecords<T>(int UserId) where T : IAssignment;
}

现在我目前有两个具有批量分配的项目。由于这些是在 EntityFramework 中完成的,Namespace1 中的分配和 Namespace2 中的分配是完全不同的事情,但受某些通用组件(ID、分配的用户、签入等)的约束,这些组件驱动所有返回它们的方法。

我认为我的主要问题是我是否做错了,是否有更好的方法来实现这一点,以便我可以将数据传输到我的控制器中,并让控制器看起来有点类似于项目的项目,同时有尽可能多的方法工作被自动处理(主要是当我需要更新时会出现“修复一个,修复所有”场景)。

下面是我如何为 namespace1 进行实现的示例:

public class Assignment
{
    ...
    public T GetAssignmentRecord<T>(int UserId, int BatchId) where T : IAssignment
    {
        var db = new Database1Context();
        return (T) Convert.ChangeType(db.Assignment.Where(c => c.UserId == UserId && c.BatchId == BatchId && c.Assigned).First(), typeof(T));
    }
}

在控制器中:

Assignment assignment = new Assignment();
var record = assignment.GetAssignmentRecord<Assignment>(userid, batchid);
// do stuff

控制器代码实际上是我假设它会工作的方式。我已经完成了作业课程,现在如果我以正确的方式做这件事,我会感到困惑。我觉得这可能不正确的原因是我基本上是在说“接口正在寻找一个泛型,我使用实体框架从数据库中获取一个强类型对象,我将它转换为泛型,当我'正在提出请求,我正在请求我最初转换为泛型的相同强类型对象。”

有没有更好的方法来做到这一点?还是我应该走的完全不同的方向?

4

3 回答 3

3

如果我正确理解你的目标是什么,我会这样做,例如这样......

interface IAssignment
{
}

interface IRepo<out T> where T : IAssignment
{
    T GetAssignmentRecord(int UserId, int BatchId);
    IEnumerable<T> GetAssignmentRecords(int UserId);
}

class AssignmentRecord : IAssignment
{
}
class AssignmentWeb : IAssignment
{
}

class RepoDb : IRepo<AssignmentRecord>
{
    public AssignmentRecord GetAssignmentRecord(int UserId, int BatchId)
    {
        //using(var db = new MyDbContext())
        //{
        //    return db.Assignment.Where(c => c.UserId == UserId && c.BatchId == BatchId && c.Assigned).First();
        //}
        return new AssignmentRecord();
    }

    public IEnumerable<AssignmentRecord> GetAssignmentRecords(int UserId)
    {
        //using(var db = new MyDbContext())
        //{
        //    return db.Assignment.Where(c => c.UserId == UserId && c.BatchId == BatchId && c.Assigned);
        //}
        return new List<AssignmentRecord> 
            {
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
                new AssignmentRecord(),
            };
    }
}

class RepoWeb : IRepo<AssignmentWeb>
{
    public AssignmentWeb GetAssignmentRecord(int UserId, int BatchId)
    {
        // fetch it from some web service...
        return new AssignmentWeb();
    }

    public IEnumerable<AssignmentWeb> GetAssignmentRecords(int UserId)
    {
        //using(var db = new MyDbContext())
        //{
        //    return db.Assignment.Where(c => c.UserId == UserId && c.BatchId == BatchId && c.Assigned);
        //}
        return new List<AssignmentWeb> 
            {
                new AssignmentWeb(),
                new AssignmentWeb(),
                new AssignmentWeb(),
            };
    }
}

class MYController
{
    public IRepo<IAssignment> Repository { get; set; } // you can inject this e.g. DI

    public IAssignment GetAssignment(int userid, int batchid)
    {
        return Repository.GetAssignmentRecord(userid, batchid);
    }

    public IEnumerable<IAssignment> GetAllAssignments(int userid)
    {
        return Repository.GetAssignmentRecords(userid);
    }
}

class ProgramAssignment
{
    static void Main(string[] args)
    {
        try
        {
            var controller = new MYController();
            controller.Repository = new RepoDb();

            IAssignment assignment = controller.GetAssignment(0, 0);
            IEnumerable<IAssignment> all = controller.GetAllAssignments(0);

            controller.Repository = new RepoWeb();

            assignment = controller.GetAssignment(0, 0);
            all = controller.GetAllAssignments(0);
        }
        catch
        {
            Console.WriteLine("");
        }
    }
}

至于为什么out- 这是我另一篇文章中的更多内容......

如何使泛型类包含一组仅包含其自己的类型或子类型的子类?

于 2013-03-28T17:49:04.907 回答
1

假设 2 Assignment 具有不同的属性(可能是一些额外的),但有些属性是相同的,并且它们来自不同的数据库,有很多方法可以做到这一点。但是“最好的”(对我来说)是通过依赖注入。

您在作业类中的活动(方法)应移至单独的“服务”类。这增加了 Assignment 的模块化,因为它只是变成了一个 POCO。

对于数据访问,创建一个单独的类(存储库)来检索/插入/更新/删除您的数据。示例如下:

public AssignmentRepository: IAssignmentRepository{
  public Assignment GetAssignmentRecord(int userId, int batchId){

  }
}

public BatchAssignmentRepository: IAssignmentRepository{
  public Assignment GetAssignmentRecord(int userId, int batchId){

  }
}

如果你问为什么有 2 个仓库而不是 1 个仓库,会不会让代码变得多余?是的,但您还必须考虑它会增加模块化。如果您在 BatchAssignment 中更改某些内容(可能更改列名、添加其他列等),那么您不需要在 Assignment 中应用相同内容,并避免您在内部使用“if batchAssignment else”逻辑。

调用者的使用将是这样的:

IAssignmentService service = new AssignmentService();
IAssignmentRepository repository = new AssignmentRepository();
Assignment a = repository.GetAssignmentRecord(userId, batchId);
service.DoSomething(a);
于 2013-03-28T17:50:55.523 回答
1

考虑一个适配器层。该层应该将传入的数据转换为通用结构/类,然后可以一致地处理,尽管有泛型。当然,它也会在“出站”端重新转换为特定数据库所期望的。这假定没有数据源具有在其他数据源中未定义的数据,或者您可以为所述缺失数据定义有效的默认值。

我想您需要针对不同项目的不同适配器。也许这是依赖注入的工作。基本上在运行时您获取所需的特定代码(适配器类)。

Unity 简介。

于 2013-03-28T17:52:48.587 回答