C # Общий статический вызов с выражением не удается - PullRequest
1 голос
/ 25 февраля 2011

Я пытаюсь получить SubSonic IActiveRecord, используя общий метод Find следующим образом:

(пожалуйста, не обращайте внимания на первый уродливый черт при поиске 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; }

Когда я вызываю MemberInfo, указывающий на функцию Find, я получаю исключение System.NotSupportedException со следующим сообщением:

"Элемент 'Tag' не поддерживается"

Однако я могу вызывать статический метод Find в любой из реальных реализаций IActiveRecord с тем же предикатом.

(для опытных с subsonic я изменил шаблон .tt, чтобы включить интерфейс ITagged во все сгенерированные классы)

Не думаю, что эта проблема особенно актуальна для SubSonic, но я подумал, что упомяну об этом, на всякий случай.

1 Ответ

3 голосов
/ 25 февраля 2011

Если я правильно понимаю, вы в основном пытаетесь создать запрос LINQ к поставщику (SubSonic), который попытается проанализировать выражения LINQ для создания запроса к базовому хранилищу данных. Проблема в том, что ITagged.Tag не существует в мире SubSonic, поэтому он не может запрашивать его. Вам нужно сделать так, чтобы ваше дерево выражений основывалось на фактическом свойстве 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);
...