【问题标题】:Repository as parameter存储库作为参数
【发布时间】:2016-07-04 14:07:19
【问题描述】:

我创建了一个通用下拉列表以在我的控制器中使用:

GenericDropDownList("myDropDown");

    private void GenericDropDownList(string dropdownName, object selectedDepartment = null) {

    var dropdownQuery = unitOfWork.SalesRepository.Get(orderBy: q => q.OrderBy(d => d.FirstName));

    ViewData[dropdownName] = new SelectList(dropdownQuery, "LastName", "LastName", selectedDepartment);
    }

这似乎工作正常。我正在尝试使unitOfWork.TestRepository 动态化,以便我可以使用函数中的每个可用存储库:

GenericDropDownList("myDropDown", SalesRepository);

    private void GenericDropDownList(string dropdownName, object repository, object selectedDepartment = null) {

    var dropdownQuery = repository.Get(orderBy: q => q.OrderBy(d => d.FirstName));

    ViewData[dropdownName] = new SelectList(dropdownQuery, "LastName", "LastName", selectedDepartment);
    }

以上行不通。我收到以下错误:

错误 CS1061 'object' 不包含 'Get' 的定义并且没有 扩展方法“Get”接受“object”类型的第一个参数 可以找到

是否可以让下拉菜单像我想要的那样动态?

【问题讨论】:

    标签: c# asp.net-mvc linq repository-pattern unit-of-work


    【解决方案1】:

    object 类没有 .Get 方法,因此它无法编译是有道理的。

    使用dynamic 可以解决这个问题,因为.Get 会在运行时解析,尽管会降低性能,并且如果.Get 在运行时不存在,则存在运行时错误的风险。

    我认为最好的方法是使用接口:

    private void GenericDropDownList(string dropdownName, IRepository repository, object selectedDepartment = null)
    {
        // ...
    }
    

    使用实体框架时,您可以使用部分类将此接口强加于存储库类:

    public partial class ThisRepository : IRepository
    {
    }
    
    public partial class ThatRepository : IRepository
    {
    }
    

    一个问题是接口不能定义一个属性,例如FirstName,因此您要么必须为此定义一个方法,要么使用Func<IRepository, string> 作为排序位。

    【讨论】:

      【解决方案2】:

      如果您想要一个动态对象,请使用 dynamic 类型。

      或者尝试将其转换为适当的类型:

      (repository as type).Get(...)
      

      【讨论】:

        【解决方案3】:

        正确的方法是让您的所有存储库都使用通用方法实现一个通用接口。

        例如,您可以创建接口IRepository,如果您希望更具体一点,可以创建IRepository<TSource>

        问题是 TSource 根据您的预期代码应该有一个 FirstName 属性。

        您确定所有存储库都将包含具有FirstName 属性的实体吗?

        如果答案是,那么你不能创建这样的泛型方法(你需要重新定义你的逻辑,或者创建一个特定的接口,该接口将包含具有此属性的实体,但你不会'无法传入任何存储库,只能传入实现此接口的存储库)。

        如果答案是,那么您可以为您的所有源实体(例如BaseEntity)创建一个基类,其中包含@987654327 @属性。

        假设答案是肯定的,那么您可以将方法的签名更改为:

        private void GenericDropDownList(string dropdownName, IRepository<TSource> repository, object selectedDepartment = null) where TSource : BaseEntity
        

        然后你就可以调用它了:

        GenericDropDownList("myDropDown", SalesRepository); //SalesRepository should implement IRepository<Sale>, where Sale : BaseEntity
        

        【讨论】:

          猜你喜欢
          • 2017-08-10
          • 2022-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多