好吧,我有以下情况:
public class Joins<TOuter, TInner, TResult>
{
public Expression<Func<TOuter, object>> outerKeySelector;
public Expression<Func<TInner, object>> innerKeySelector;
public Expression<Func<TOuter, TInner, object>> resultSelector;
public IEnumerable<TResult> r;
}
public class Test<T>
{
public IEnumerable<TResult> Join<TInner, TResult>(
Expression<Func<T, object>> outerKeySelector,
Expression<Func<TInner, object>> innerKeySelector,
Expression<Func<T, TInner, TResult>> resultSelector) where TInner : class
{
var join = new Joins<T, TInner, TResult>();
join.innerKeySelector = innerKeySelector;
join.outerKeySelector = outerKeySelector;
return join.r;
}
}
要创建联接方法,我依赖链接:http://msdn.microsoft.com/en-us/library/bb534644(v=vs.100).aspx
但是,当我尝试调用该方法时,无法识别 TInner ,使得该方法无效,我返回以下错误:
无法将表达式'type'转换为返回类型'TResult'
注意: '加入' 这个类纯粹是一个测试,没有一个是明确的, var'r' 仅用于测试,仅用于促进返回。
预期用途示例:
var test = new Test<User>().Join<Permission>(u => u.Id, p => p.IdUser, (u, p) => new { Id = u.Id , Area = p.Area });
更多详情:
如上所述,无法识别 TInner ,因此我无法拨打正确的方法。
作为测试,我这样做了:
var test = new Test<User>().Join<Permission>(u => u.Id, p => p.ToString(), (u, p) => new {Id = u.Id, Name = p.ToString()});
我知道 p.ToString() 不正确,但是没有识别所指示的类的属性(在Permission情况下),然后放入ToString()只是为了完成方法的写作。
修改
我需要在foreach / for
中使用结果示例:
foreach(var obj in test)
{
var id = obj.Id;
var area = obj.Area;
.
.
.
}
答案 0 :(得分:0)
要使其有效,您应该执行以下操作:
var test = new Test<User>().Join<Permission, object>(u => u.Id, p => p.IdUser, (u, p) => new { Id = u.Id, Area = p.Area });
// ^^ (resolve the second type argument as well)
定义以下内容时:
public TResult Join<TInner, TResult>
然后你应该给编译器一个提示,显示哪个类型(而不是任何,提到类型参数:TInner,TResult),或者它必须以某种方式自动识别编译器(然后你可以从显式定义中省略它),但在你的情况下你必须明确地这样做。
看看this answer。尽管这个问题也与扩展方法有关,但是对于要解析的类型参数的逻辑有很好的解释。
修改强>
但是object
,肯定不是最好的决定,因为你以后不能对该对象做任何事情(特别是,如果这是一个匿名类型)。
所以,你应该改变它,例如,通过以下方式:
public class Test<T, TInner> where TInner : class where T : class
{
public IEnumerable<TResult> Join<TResult>(
...
Expression<Func<T, TInner, TResult>> resultSelector)
之后你可以按如下方式使用它:
var test = new Test<User, Permission>()
.Join(u => u.Id, p => p.IdUser, (u, p) => new { Id = u.Id, Area = p.Area });
修改强>
如果您需要将TInner
和TResult
传递给Join
方法,那实际上是不可能的。匿名类只能由编译器自动解析 - 您无法明确指定它。
那么,你可以解决它的唯一方法,如下:
var test = new Test<User>().Join<Permission, dynamic>(...
允许您使用LinQ
.Where(
方法使用结果,但是没有智能感知支持(除非您为Join输出创建具体类)。