C#泛型/接口 - 根据类返回不同的类型 [英] C# Generics / Interfaces - Returning different types based on the class

查看:178
本文介绍了C#泛型/接口 - 根据类返回不同的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于工作,我们有特定类型的记录,但每个项目都有自己的实施。列和诸如此类是不同的,但通常过程是相同的(记录被分成批次,分配批次,批次完成,批次返回,批次发送等)。许多列也很常见,但有时会出现名称更改(在另一个ID中的BatchId,[Column(name)]处理此问题)。



目前这就是我使用界面中给出的常用组件实现批分配功能的原因:

  public interface IAssignment 
{
//属性
...
//方法
T GetAssignmentRecord< T> (int UserId,int BatchId)其中T:IAssignment;
列表< T> GetAssignmentRecords< T>(int UserId)其中T:IAssignment;
}

现在我有两个有批次分配的项目。由于这些都是在EntityFramework中完成的,所以命名空间1中的赋值和命名空间2中的赋值是完全不同的东西,但是受到某些常用组件(ID,指定用户,签入等)的约束,这些组件会驱动所有返回它们的方法。



我认为我的主要问题是如果我不正确地做到这一点,并且如果有更好的方法来实现这一点,我可以将数据传入我的控制器并获得控制器看起来有点类似于项目,但是有很多自动处理方法的工作(主要是为了在我需要更新时发生修复一个,修复所有情况)。



以下是我为namespace1执行实现的示例:

  public class赋值
{
...
public T GetAssignmentRecord< T>(int UserId,int BatchId)其中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));




$ p
$ b $ p $在控制器中:

 赋值赋值=新赋值(); 
var record = assignment.GetAssignmentRecord< Assignment>(userid,batchid);
//做东西

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

有没有更好的方法来做到这一点?或者一个完全不同的方向我应该去?

解决方案

提供我正确理解你的目标是什么,这样... ...

$ p $ 接口IAssignment
{
}

接口IRepo< out T> 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)
{
//使用(var db = new MyDbContext())
// {
// return db.Assignment.Where(c => c.UserId == UserId&& c.BatchId == BatchId&& c.Assigned).First();
//}
返回新的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);
//}
返回新的List< AssignmentRecord>
{
新的AssignmentRecord(),
新的AssignmentRecord(),
新的AssignmentRecord(),
新的AssignmentRecord(),$ b $新的AssignmentRecord(),
新的AssignmentRecord(),
新的AssignmentRecord(),
新的AssignmentRecord(),
};
}
}

class RepoWeb:IRepo< AssignmentWeb>
{
public AssignmentWeb GetAssignmentRecord(int UserId,int BatchId)
{
//从某个Web服务获取它...
返回新的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);
//}
返回新列表< AssignmentWeb>
{
新的AssignmentWeb(),
新的AssignmentWeb(),
新的AssignmentWeb(),
};
}
}

class MYController
{
public IRepo< IAssignment> Repository {get;组; } //你可以注入这个例如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();

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



至于为什么 out - 这里是我的其他帖子中的更多内容......




For work, we have specific types of records that come in, but each project has its own implementation. The columns and the like are different, but in general the process is the same (records are broken into batches, batches are assigned, batches are completed, batches are returned, batches are sent out, etc.). Many of the columns are common, too, but sometimes there are name changes (BatchId in one vs Id in another. [Column("name")] takes care of this issue).

Currently this is what I have for the implementation of the batch assignment functionality with the common components given in the interface:

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

Now I currently have two projects that have batch assignment. Due to these being done in EntityFramework, Assignment in Namespace1 and Assignment in Namespace2 are completely different things but are bound by certain common components (an ID, an assigned user, checked in, etc.) which drive all of the methods for returning them.

I think my main question is if I'm doing this incorrectly and if there is a better way to achieve this such that I can pipe data into my Controllers and have the controllers look somewhat similar project to project while having as much of the method work being handled automatically (primarily so that a "fix one, fix all" scenario occurs when I need to do updates).

Here's an example of how I'm doing the implementation for 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));
    }
}

In the Controller:

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

The controller code is actually how I'm assuming it would work. I've completed through the Assignment class and now I'm perplexed if I'm doing it the proper way. The reason I feel this may be incorrect is I'm basically saying "The interface is looking for a generic, I'm getting a strong typed object from the database using entity framework, I'm casting it to a generic, and when I'm making the request, I'm asking for the same strong typed object that I converted to generic initially."

Is there a better way of doing this? Or a completely different direction I should be going?

解决方案

Providing I understood correctly what your goal is, I'd do it e.g. this way...

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("");
        }
    }
}

As to why the out - here is some more in my other post...

How to make generic class that contains a Set of only its own type or subtypes as Children?

这篇关于C#泛型/接口 - 根据类返回不同的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆