存储库作为参数
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
属性 的实体吗?
如果答案是否,那么你不能创建这样的通用方法(你需要重新定义你的逻辑,或者创建一个特定的接口,该接口将具有这个属性,但是你将无法传入任何存储库,只能传入实现此接口的存储库。
如果答案是是,那么您可以为所有源实体创建一个基础class(BaseEntity
,例如),它会有 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>
作为排序位。
我创建了一个通用下拉列表以在我的控制器中使用:
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
属性 的实体吗?
如果答案是否,那么你不能创建这样的通用方法(你需要重新定义你的逻辑,或者创建一个特定的接口,该接口将具有这个属性,但是你将无法传入任何存储库,只能传入实现此接口的存储库。
如果答案是是,那么您可以为所有源实体创建一个基础class(BaseEntity
,例如),它会有 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:
将此接口强加到存储库 classespublic partial class ThisRepository : IRepository
{
}
public partial class ThatRepository : IRepository
{
}
一个问题是接口可以不能定义一个属性比如FirstName
,所以你要么必须为此定义一个方法,或者使用 Func<IRepository, string>
作为排序位。