Question

I am trying to fetch a SubSonic IActiveRecord by reflecting on the generic method Find, as follows:

(please ignore the first draft ugliness in locating the 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 simply defines

  string Tag { get; set; }

When I Invoke the MemberInfo pointing to the Find function, I am getting a System.NotSupportedException being thrown, with the following message:

"The member 'Tag' is not supported"

I am, however, able to call the static Find method on any of the actual IActiveRecord implementations with the same predicate.

(for those savvy with subsonic, I have modified the .tt template to include the ITagged interface on all generated classes)

I don't think this issue is particularly relevant to SubSonic, but thought I'd mention it, just in case.

Was it helpful?

Solution

If I'm understanding correctly, you're basically trying to create a LINQ query against a provider (SubSonic) that will try to parse out the LINQ expressions to produce a query against an underlying data store. The problem is that ITagged.Tag does not exist in SubSonic's world, so it cannot query against it. You're going to need to make your expression tree be based on the actual T.Tag property instead.

Something along these lines should work:

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);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top