C# 使用多个类

C# 使用多个类,c#,C#,我有三门C#课程,我正在努力学习。这些类非常相似,但有一些小的变化。因为每个类都是不同的,并且存储在一个单独的DB表中,所以我需要函数来返回每个类类型,但是因为它们非常相似,所以几乎可以在我的控制器中使用相同的函数来编写它们 我不希望在我的控制器中编写完全相同的函数集,除了输入/输出类之外没有任何区别,但我一辈子都不知道如何编写 我尝试过多态性,但老实说,它完全混淆了我将类分离出来的地方,因为我无法访问父类中的子类属性,这简直是一团糟 如何正确使用这三个不同但相似的类? 这是我目前拥有的,但它不

我有三门C#课程,我正在努力学习。这些类非常相似,但有一些小的变化。因为每个类都是不同的,并且存储在一个单独的DB表中,所以我需要函数来返回每个类类型,但是因为它们非常相似,所以几乎可以在我的控制器中使用相同的函数来编写它们

我不希望在我的控制器中编写完全相同的函数集,除了输入/输出类之外没有任何区别,但我一辈子都不知道如何编写

我尝试过多态性,但老实说,它完全混淆了我将类分离出来的地方,因为我无法访问父类中的子类属性,这简直是一团糟

如何正确使用这三个不同但相似的类?

这是我目前拥有的,但它不起作用,因为
task
不能在
switch
语句中声明。(这将最理想地解决我的问题)。我也不能在
开关
外部声明泛型变量,并在
开关
内部为其指定类型,因为C#不允许这样做

var type = _projectService.GetTaskTypeById(id);
/* object task; doesn't work. I can declare it inside the switch statement
   but it doesn't "become" the new type (the last line throws an error: 
   "object does not contain a definition for ToModel()")
*/

switch (type)
{
    case "MS":
        var task = _projectService.GetMSTaskById(id);
        break;
    case "TL":
        var task = _projectService.GetTLTaskById(id);
        break;
    case "ET":
        var task = _projectService.GetETTaskById(id);
        break;
    default:
        // throw error
}

task.ToModel();

您最希望的是使用继承或接口。从一个具有所有相似函数的基类开始,然后让三个不同的类中的每一个继承这个类。最后,不要使用“var”来定义对象任务,而是使用switch语句之前定义的基类。

您最好希望使用继承或接口。从一个具有所有相似函数的基类开始,然后让三个不同的类中的每一个继承这个类。最后,不要使用“var”来定义对象任务,而是使用switch语句之前定义的基类。

正确的答案是声明一个公共基类或接口,但您说“我尝试了多态性,但是”。我不知道你尝试了什么(或如何),但假设

  • 您确信所有类都有一个
    ToModel()
    方法
  • 为类声明公共接口或基类是不实际的
  • 您正在使用.NET 4.0或更高版本
  • 你能行

    var type = _projectService.GetTaskTypeById(id);
    
    dynamic task;
    
    switch (type)
    {
        case "MS":
            task = _projectService.GetMSTaskById(id);
            break;
        case "TL":
            task = _projectService.GetTLTaskById(id);
            break;
        case "ET":
            task = _projectService.GetETTaskById(id);
            break;
        default:
            throw new NotSupportedException("Unsupported Task Type: " + type);
    }
    
    task.ToModel();
    

    正确的答案是声明一个公共基类或接口,但您说“我尝试了多态性,但是”。我不知道你尝试了什么(或如何),但假设

  • 您确信所有类都有一个
    ToModel()
    方法
  • 为类声明公共接口或基类是不实际的
  • 您正在使用.NET 4.0或更高版本
  • 你能行

    var type = _projectService.GetTaskTypeById(id);
    
    dynamic task;
    
    switch (type)
    {
        case "MS":
            task = _projectService.GetMSTaskById(id);
            break;
        case "TL":
            task = _projectService.GetTLTaskById(id);
            break;
        case "ET":
            task = _projectService.GetETTaskById(id);
            break;
        default:
            throw new NotSupportedException("Unsupported Task Type: " + type);
    }
    
    task.ToModel();
    

    就我个人而言,我会按照

    public interface IProjectTask
    {
        Task GetTaskById(int id);
    }
    
    public enum ProjectTaskTypes
    {
        MS = 1,
        TL = 2,
        ET = 3
    }
    public class ProjectTaskFactory
    {
        public static IProjectTask GetInstance(ProjectTaskTypes projectTaskType,
                                               int projectTaskId)
        {
            IProjectTask task;
            switch(projectTaskType)
            {
                case ProjectTaskTypes.MS:
                    task = new MSProjectTask(projectTaskId);
                    break;
                case ProjectTaskTypes.TL:
                    task = new TLProjectTask(projectTaskId);
                    break;
                case ProjectTaskTypes.ET:
                    task = new ETProjectTask(projectTaskId);
                    break;
                default:
                    // throw error
            }       
            return task;
        }
    }
    
    //usage
    var projectTask = ProjectTaskFactory.GetInstance(type);
    projectTask.ToModel()
    
    作为旁注,我觉得为项目类型创建枚举更好,代码中没有神奇的字符串,可读性更好


    将它们分开不仅是单一责任模式的一部分,而且意味着编写单元测试可能更容易。

    就我个人而言,我会按照

    public interface IProjectTask
    {
        Task GetTaskById(int id);
    }
    
    public enum ProjectTaskTypes
    {
        MS = 1,
        TL = 2,
        ET = 3
    }
    public class ProjectTaskFactory
    {
        public static IProjectTask GetInstance(ProjectTaskTypes projectTaskType,
                                               int projectTaskId)
        {
            IProjectTask task;
            switch(projectTaskType)
            {
                case ProjectTaskTypes.MS:
                    task = new MSProjectTask(projectTaskId);
                    break;
                case ProjectTaskTypes.TL:
                    task = new TLProjectTask(projectTaskId);
                    break;
                case ProjectTaskTypes.ET:
                    task = new ETProjectTask(projectTaskId);
                    break;
                default:
                    // throw error
            }       
            return task;
        }
    }
    
    //usage
    var projectTask = ProjectTaskFactory.GetInstance(type);
    projectTask.ToModel()
    
    作为旁注,我觉得为项目类型创建枚举更好,代码中没有神奇的字符串,可读性更好


    将它们分开不仅是单一责任模式的一部分,还意味着编写单元测试可能更容易。

    Declare
    task
    在交换机外部使用具体或基本类型。
    GetXXTaskById
    是否返回相同类型的派生?如果你能对任何一种类型调用
    .ToModel
    ,他们将不得不这样做……我认为你真正的问题是我试过的句子,但是。。。您应该展示这些类的公共部分的(部分)实现,以及您如何使用多态性方法失败。如果您不喜欢继承,那么也可以使用接口。在您的例子中,它可以包含
    .ToModel()
    方法,并在所有3个类上实现它。您能显示其中两个类的代码吗?如果它们几乎是精确的,那么应该可以将相同的部分提取到一个模型中(类、抽象类、接口)。@Steve我已经重写了代码,但它在某个时候签入到TFS中,以便我可以在必要时进行挖掘。本质上,我有一个父类(
    Task
    ),由三个子类实现(
    MS
    TL
    ET
    )。我一直遇到问题,因为我不知道或者找不到方法a)在调用父对象时获取子对象的参数,或者b)在使用EF-TPH继承时获取条目的类型。这就是为什么我放弃了,转而为每个类创建单独的类,结果造成了现在的混乱。使用具体类型或基类型在交换机外部声明
    task
    GetXXTaskById
    是否返回相同类型的派生?如果你能对任何一种类型调用
    .ToModel
    ,他们将不得不这样做……我认为你真正的问题是我试过的句子,但是。。。您应该展示这些类的公共部分的(部分)实现,以及您如何使用多态性方法失败。如果您不喜欢继承,那么也可以使用接口。在您的例子中,它可以包含
    .ToModel()
    方法,并在所有3个类上实现它。您能显示其中两个类的代码吗?如果它们几乎是精确的,那么应该可以将相同的部分提取到一个模型中(类、抽象类、接口)。@Steve我已经重写了代码,但它在某个时候签入到TFS中,以便我可以在必要时进行挖掘。本质上,我有一个父类(
    Task
    ),由三个子类实现(
    MS
    TL
    ET
    )。我一直遇到问题,因为我不知道或者找不到方法a)在调用父对象时获取子对象的参数,或者b)在使用EF-TPH继承时获取条目的类型。这就是为什么我放弃了,转而为每一个人单独上课,结果导致了我的失败