繁体   English   中英

Web API跨两个类?

[英]Web api cross two classes?

我有两节课

public class C1 : ApiController { ... 
  public List<C1> GetAll() { ....} // GetAll(string search = null)
}

public class C2 : ApiController { ... 
  public List<C2> GetAll() { ....} // GetAll(string search = null).
}

然后,我需要向每个类添加搜索功能。 因此,我向每个GetAll()添加了一个搜索参数,作为GetAll(string search = null) 如果search为null,则方法将返回所有列表。 否则,它将返回过滤的结果列表。

现在,我需要补充的是在搜索的数据库表的搜索功能C1C2和返回两个列表C1C2SearchC1AndC2ViewModel )。 我应该在哪里实现该功能? 还是应该仅为此函数创建一个新类?

public class SearchC1AndC2ViewModel { 
  public List<C1> C1s; 
  public List<C2> C2s; 
}

即将实施的Web API

public SearchC1AndC2ViewModel Search(string search)

首先,我假设您在search和GetAll方法中滥用了type参数,因为它现在看起来与您的控制器相同。

您似乎正在寻找一种共享通用解决方案的机制。 有多种方法可以实现您想要的目标。

选项1:基本控制器类

为这两个控制器定义一个基类,并在那里实现一个通用的搜索方法。 在控制器中正确放置数据访问逻辑并不是理想的选择,因此您可能会将逻辑移到其他位置,然后从此处调用。 在这种情况下,代码如下所示:

public abstract class CustomControllerBase<T> : ApiController
{
    public List<T> GetAll(string filter = null)
    {
        // Common code goes here.
        // At some point you may need some customization based on the actual implementation
        return this.RetrieveRecords(filter);
    }

    protected abstract List<T> RetrieveRecords(string filter);
}

public class Controller1 : CustomControllerBase <C1>
{
    protected override List<C1> RetrieveRecords (string filter) {
        // Custom logic goes here
    }
}

public class Controller2 : CustomControllerBase <C2>
{
    protected override List<C2> RetrieveRecords (string filter) {
        // Custom logic goes here
    }
}

选项2:委派到数据层

第二种选择是为数据访问操作提供专用的类,并使其具有通用性,以便可以将其重用于多种类型。 如果您要从数据库(或某些其他数据存储)中检索的这两个实体之间的唯一区别是实体的类型和源(表名称),则可以使数据类构造函数具有这些参数。

public class DataAccessHandler<T>
{
    private Func<QueryResultItem, T> queryResultProcessingLogic;

    public DataAccessHandler(Func<QueryResultItem, T> queryResultProcessingLogic)
    {
        // Validation goes here
        this.queryResultProcessingLogic = queryResultProcessingLogic;
    }

    public List<T> Retrieve(string filter = null)
    {
        QueryResult queryResult = // Retrieve query results given query. this is your custom implementation. QueryResult type is an abstraction, you'll have to replace it with the actual type you use. I'm sharing just the concept here.
        return queryResult.Select(item=>queryResultProcessingLogic(item)).ToList();
    }
}

public class Controller1 : ApiController
{
    private readonly DataAccessHandler<C1> dataHandler;

    public Controller1 ( DataAccessHandler<C1> dataHandler)
    {
        // Validate arguments here

        this.dataHandler = dataHandler;
    }

    public List<C1> GetAll(string filter)
    {
        return this.dataHandler.GetAll(filter);
    }
}

最好的方法是结合两个选项:)

希望这可以帮助。

如果问题仅在于为该函数的返回类型创建一个类,则可以让它返回Tuple<List<C1>, List<C2>>


现在,如果您希望将其他控制器的GetAll方法重用到新的控制器中,那么欢迎使用类组合 您不能使一个控制器同时继承C1控制器和C2控制器,因为一个类不能从一个以上的类继承。 相反,您必须创建一个空接口并使用GetAll方法对其进行扩展,但是由于您将从这两个接口继承,这些方法将发生冲突,因为对GetAll的调用将变得模棱两可,因此您还必须更改方法名称。 但是C1C2实际上是从ApiController继承的类,并且接口不能从类继承,因此您必须制作接口并使C1C2都从它们和ApiController继承。 我不知道是谁发明了这个,但是实际上这是“正确”的方式,而且很混乱 开始了:

// First define the interfaces
public interface IC1 { }
public interface IC2 { }

// Then extend the with the GetAll methods
public static class ICExtensions
{
  public static List<C1> GetAllC1(this IC1, string search = null) { ... } 
  public static List<C2> GetAllC2(this IC2, string search = null) { ... }
}

// These are now your controllers
public class C1Controller : ApiController, IC1 { ... }
public class C2Controller : ApiController, IC2 { ... }

// And here is the new controller that has the two GetAll methods
public class C1AndC2Controller : ApiController, IC1, IC2 { ... }

现在,您可以自由实现GetAll的方法C1AndC2Controller ,它可以返回一个新的类, Tuple ,不管你想要它。

暂无
暂无

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

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