带有Expression的C#通用静态调用失败

时间:2011-02-25 11:35:45

标签: c# linq reflection static subsonic

我试图通过反映泛型方法Find来获取SubSonic IActiveRecord,如下所示:

(请忽略查找MethodInfo时的第一个丑陋草案)

private T GetSavedRecord<T>(string tag) where T : IActiveRecord, ITagged 
{
  //Some internal caching stuff

  ...

  MethodInfo info = typeof(T).GetMethods(BindingFlags.Static | BindingFlags.Public)
                             .FirstOrDefault(m => m.Name == "Find" && m.GetParameters().Count() == 1);

  Expression<Func<T, bool>> predicate = e => e.Tag == tag;                            

  T record = ((IList<T>)info.Invoke(null, new object[] { predicate })).FirstOrDefault(); 

  return //cached record
}

ITagged只是定义了

  string Tag { get; set; }

当我调用指向Find函数的MemberInfo时,我将抛出一个System.NotSupportedException,并显示以下消息:

  

“不支持会员'标签'”

但是,我可以使用相同的谓词在任何实际的IActiveRecord实现上调用静态Find方法。

(对于那些精通亚音速的人,我修改了.tt模板,在所有生成的类中包含ITagged接口)

我不认为这个问题与SubSonic特别相关,但我想我会提到它,以防万一。

1 个答案:

答案 0 :(得分:3)

如果我理解正确,你基本上是在尝试针对提供者(SubSonic)创建LINQ查询,该提供者将尝试解析LINQ表达式以生成针对底层数据存储的查询。问题是,在SubSonic的世界中不存在ITagged.Tag,因此无法对其进行查询。您将需要使表达式树基于实际的T.Tag属性而不是。

这些方面应该有效:

var tagMember = typeof(T).GetProperty("Tag");
var eParam = Expression.Parameter(typeof(T), "e");
var predicate = 
    Expression.Lambda<Func<T, bool>>(
        Expression.Equal(
            Expression.Property(eParam, tagMember), 
            Expression.Constant(tag)
        ),
        eParam);