问题
有没有办法在C#中(在辅助类或其他东西中)只定义一个方法,而不知道要返回哪种类型?
长解释 我收到以下错误:
无法投射类型的对象 System.Data.Objects.ObjectQuery
1[WerkStageNu.Vacancies]' to type 'System.Linq.IQueryable
1 [WerkStageNu.Models.IFilteredEntities]”。
我有一个ListingsController,通过数据库中的当前职位空缺进行搜索:
public ActionResult Search(int? page, string branchid, string hoursago, string jobtypeid, string educationlevelid, string careerlevelid)
{
string searchResult = string.Empty;
const int pageSize = 10;
IQueryable<IFilteredEntities> selectedListings = (IQueryable<IFilteredEntities>)Repository.Instance._entities.Vacancies.AsQueryable();
Dictionary<string, string> filterParams = new Dictionary<string, string>() {
{"branchid", branchid}, {"hoursago", hoursago}, {"jobtypeid", jobtypeid}, {"educationlevelid", educationlevelid}, {"careerlevelid", careerlevelid}};
selectedListings = FilterByIDHelper.Filter(selectedListings, filterParams);
var paginatedDinners = new PaginatedList<Vacancies>(((IQueryable<Vacancies>)selectedListings).ToList(), page ?? 0, pageSize);
return View("Index", paginatedDinners);
}
现在,这次搜索仅针对职位空缺。但是可以想象我们在整个地方都搜索了相同的例程,因此我想调用相同的方法来获取不同的类型。对于这种情况,我创建了一个接口,IFilteredEntities。在我的部分班级空缺职位(部分班级,班级职位空缺由我的数据库实体框架生成)我只是这样做:
public partial class Vacancies : IFilteredEntities
当然,实现Interface中没有默认实现的方法。在我的界面中我有:
interface IFilteredEntities
{
string EducationLevelID { get; set; }
string BrancheID { get; set; }
string CareerLevelID { get; set; }
string JobTypeID { get; set; }
Branches Branches { get; set; }
DateTime? DateOfCreation { get; set; }
CareerLevels CareerLevels { get; set; }
JobTypes JobTypes { get; set; }
EducationLevels EducationLevels { get; set; }
}
为方便起见,我上传了两个辅助类PaginatedList和FilterCriteriaHelper here和here。
现在,将进行实际过滤的方法放在另一个帮助器类中:FilterByIDHelper.cs。
public static IQueryable<IFilteredEntities> Filter(IQueryable<IFilteredEntities> collection, Dictionary<string, string> filterParams)
{
if (filterParams.ContainsKey("branchid")) collection = FilterByBranchId(collection, filterParams["branchid"]);
if (filterParams.ContainsKey("hoursago")) collection = FilterByHoursAgo(collection, filterParams["hoursago"]);
if (filterParams.ContainsKey("jobtypeid")) collection = FilterByJobTypeId(collection, filterParams["jobtypeid"]);
if (filterParams.ContainsKey("educationlevelid")) collection = FilterByEducationLevelId(collection, filterParams["educationlevelid"]);
if (filterParams.ContainsKey("careerlevelid")) collection = FilterByCareerLevelId(collection, filterParams["careerlevelid"]);
return collection;
}
public static IQueryable<IFilteredEntities> Filter(IQueryable<IFilteredEntities> collection, Dictionary<string, string> filterParams)
{
if (filterParams.ContainsKey("branchid")) collection = FilterByBranchId(collection, filterParams["branchid"]);
if (filterParams.ContainsKey("hoursago")) collection = FilterByHoursAgo(collection, filterParams["hoursago"]);
if (filterParams.ContainsKey("jobtypeid")) collection = FilterByJobTypeId(collection, filterParams["jobtypeid"]);
if (filterParams.ContainsKey("educationlevelid")) collection = FilterByEducationLevelId(collection, filterParams["educationlevelid"]);
if (filterParams.ContainsKey("careerlevelid")) collection = FilterByCareerLevelId(collection, filterParams["careerlevelid"]);
return collection;
}
为方便起见,这是我的解决方案资源管理器的一部分图片:
Solution Explorer http://www.bastijn.nl/zooi/solutionexplorer.png
简而言之:
我尝试做的不是像:
selectedListings = Repository.Instance._entities.Vacancies.AsQueryable();
Dictionary<string, string> filterParams = new Dictionary<string, string>() {
{"branchid", branchid}, {"hoursago", hoursago}, {"jobtypeid", jobtypeid}, {"educationlevelid", educationlevelid}, {"careerlevelid", careerlevelid}};
selectedListings = FilterByIDHelper.Filter(selectedListings, filterParams);
var paginatedDinners = new PaginatedList<Vacancies>(selectedListings.ToList(), page ?? 0, pageSize);
return View("Index", paginatedDinners);
使用接口调用显示的变体,因此我只需要定义te“Filter”方法一次,而不是所有类/模型。 现在请注意,所有这些都要编译!问题是我收到以下错误:
Unable to cast object of type 'System.Data.Objects.ObjectQuery`1[WerkStageNu.Vacancies]' to type 'System.Linq.IQueryable`1[WerkStageNu.Models.IFilteredEntities]'.
我希望我没有忘记任何信息,但我已经盯着这段代码了一段时间。可能会忘记某种关系或某种东西,如果我这样做就会问它:)。
-------------------------------------------- ---------
评论后编辑
-------------------------------------------- ---------
O crap,没关系这部分,我忘了AsEnumerable,仍然使用AsQueryable。
答案 0 :(得分:5)
在我看来,这是一个协方差与逆变问题。基本上,IQueryable<Vacancies>
不是IQueryable<IFilteredEntities>
的子类型,即使Vacancies实现了IFilteredEntities。因此,具有强制转换的行导致运行时错误。所以,而不是做演员而不是尝试:
IEnumerable<IFilteredEntities> selectedListings =
Repository.Instance._entities.Vacancies.AsQueryable()
.OfType<IFilteredEntities>();
这样做会将集合的每个元素投影到IFilteredEntities类型。
另一种选择是重写过滤器方法,以便使用泛型,如下所示:
public static IEnumerable<T> Filter<T>(
IEnumerable<T> collection, IDictionary<string, string> filterParams)
where T : IFilteredEntities
{
...
}
然后,这将允许您传入包含从IFilteredEntities派生的任何类型的集合,并获取相同类型的集合。如果你正在使用C#3,你甚至不必指定类型参数,如果它可以由编译器隐式确定。