存储库作为参数

Repository as parameter

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

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

以上方法无效。我收到以下错误:

Error CS1061 'object' does not contain a definition for 'Get' and no extension method 'Get' accepting a first argument of type 'object' could be found

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

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

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

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

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

例如,您可以创建接口 IRepository,或者 IRepository<TSource> 如果您希望它更具体一些。

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

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

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

如果答案是,那么您可以为所有源实体创建一个基础classBaseEntity,例如),它会有 FirstName 属性.

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

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

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

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

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

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

使用 Entity Framework 时,您可以通过使用部分 classes:

将此接口强加到存储库 classes
public partial class ThisRepository : IRepository
{
}

public partial class ThatRepository : IRepository
{
}

一个问题是接口可以不能定义一个属性比如FirstName,所以你要么必须为此定义一个方法,或者使用 Func<IRepository, string> 作为排序位。