繁体   English   中英

返回具有子属性 C#、.NET 的父 class

[英]Return parent class with child properties C#, .NET

我有两个具有多个共同属性的类,但它们也有自己的属性。 我创建了一个基本 class 和两个子类,但现在在我的 API 中,我想要一个返回类型,因为我们为两个孩子都有一个 API。 我应该如何回应 class?

基础 Class 响应


public class BaseClass
{
    public string? id { get; set; }

    public string? Name { get; set; }
    
    public string Address { get; set; }
    
    public string Type {get; set;}

    public string? PhoneNumber { get; set; } = null;
}

孩子 1

public class Child1 : BaseClass
{
    public string? RollNumber { get; set; }
    
    public string HighSchoolGrade{ get; set; }

}

孩子 2

public class Child2 : BaseClass
{
    public string? Height { get; set; }
    
    public string Weight{ get; set; }

}

现在在 API 中,我的反应应该是 object

  public async Task<BaseClass?> GetAllData(string id)
    {
        //Query
        var data = //Query
        if (data.type = ChildX){
        return //Run the mapper to convert to Child1 DTO
        
        } else {

        return  //Run the mapper to convert to Child2 DTO
        }
    }

如果我执行上述操作,它不会返回子类的属性,并且只返回基本 class 因为响应 object。 有没有办法拥有一个特定的响应类型,其中包括 Child1 或 Child2 属性以及基于 data.type

我们使用的是文档数据库,因此数据库中没有特定属性,因为它是 JSON 数据。 我希望这些类是分开的,因为将来我们可以拥有更多的属性。 有没有办法拥有通用响应类型或只是删除响应类型? 在这种情况下,最佳实践是什么?

相反,它正在返回所有字段和属性。 但是,无法保证在编译时返回哪种类型,因此它们在编译时不会自动可用,因此您必须在运行时强制转换它。

为了解释,想象一下如果你写了这个:

var result = await GetAllData();
Console.WriteLine(result.RollNumber); //This would fail if Child2 was returned
Console.WriteLine(result.Height); //This would fail if Child1 was returned

相反,您必须检查类型并进行转换:

var result = await GetAllData();
if (result is Child1)
{
    Console.WriteLine(((Child1)result).RollNumber);
}
if (result is Child2)
{
    Console.WriteLine(((Child2)result).Height);
}

由于这很常见,因此有各种 c# 结构可以帮助您,例如您也可以编写

var c1= result as Child1;
if (c1!= null) Console.WriteLine(c1.RollNumber);

或者

switch (result)
{
    case Child1 c1:
        Console.WriteLine(c1.RollNumber);
        break;
    case Child1 c2:
        Console.WriteLine(c2.Height);
        break;
}

后者被称为“模式匹配”

作为替代方案,您可以使用dynamic ,如下所示:

dynamic result = await GetAllData();
Console.WriteLine(result.RollNumber); 
Console.WriteLine(result.Height); 

然而,这并不能很好地执行(因为它必须在运行时使用反射来查找属性),如果您不小心访问了错误的属性,这将引发令人讨厌的运行时错误。 所以是气馁的。

我建议您使用模式匹配方法,因为这就是它的用途。

所以,你不能从同一个 class 返回不同的类型,你可以做一些通用的事情,但调用者需要指定类型,如果调用者可以这样做,他们可以调用正确的类型化重载。

相反,您可以稍微扩展您的基础 class,

public abstract class BaseClass
{
    ...

    public abstract SomeTypeIndicator GetType();
}

这样调用者就可以询问实例它是什么类型。

从任务中删除基础 class,通常是

public async Task<ActionResult> GetAllData(string id)
{
}

当你从 API 获取数据时使用类似的东西

var data = JObject.Parse(response.Content);
        if (data["type"] = "ChildX")
       return data.ToObject<Child1>();
   else   return data.ToObject<Child1>();
    

首先将动作签名更改为:

  public async Task<IActionResult> GetAllData(string id)
  {
       //Code
  }

然后你可以像这样在映射上使用条件:

public async Task<IActionResult> GetAllData(string id)
{
       var query= table.Find(_ => true);
      if (data.type = ChildX)
      {
          var data1 = query.Project(TableMapping.MapChild1()).SingleOrDefualt();
          return data1;
       
      } 
      else 
      {
          var data2 = query.Project(TableMapping.MapChild2()).SingleOrDefualt();
          return data2;
      }
}

public static class TableMapping
{
   public static FindExpressionProjectionDefinition<YOUR_TABLE, Child1> MapChild1()
   {
     var config = new FindExpressionProjectionDefinition<YOUR_TABLE, Child1>(tbl => new Child1
                {
                   //populate your model like this:
                   RollNumber =  tbl.roleNumber  
                });
    return config;
   }

   public static FindExpressionProjectionDefinition<YOUR_TABLE, Child2> MapChild2()
   {
     var config = new FindExpressionProjectionDefinition<YOUR_TABLE, Child2>(tbl => new Child2
                {
                   //populate your model like this:
                   Height =  tbl.height  
                });
    return config;
   }
}

如果您不是 Document Db,则可以在方法签名中使用Experssion<Func<TABLE,Child1>>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM