0

好吧,我有以下情况:

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”

注意:'Joins'类纯粹是一个测试,没有一个是确定的,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;
    .
    .
    .
}
4

1 回答 1

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),或者它必须以某种方式被编译器自动识别(然后你可以从显式定义中省略它),但在你的情况下,你必须明确地这样做。


看看这个答案。尽管这个问题也与扩展方法有关,但是对于需要解析的类型参数的逻辑,有一个很好的解释。

编辑:

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

编辑:

如果您需要将TInnerandTResult传递给Join方法,那是不可能的。匿名类只能由编译器自动解析 - 您不能明确指定它。

因此,您可以解决它的唯一方法,如下所示:

var test = new Test<User>().Join<Permission, dynamic>(...

这将允许您使用您的结果然后使用LinQ .Where(方法,但是,没有智能感知支持(除非您为 Join 输出创建一个具体的类)。

于 2013-11-13T11:53:28.847 回答