Thanks for your detailed report (with repro!). The reason for the
exception is that re-linq's partial evaluation (written for .NET 3.5)
doesn't correctly deal with .NET 4's additional expression types. For
details, see "https://www.re-motion.org/jira/browse/RM-4465".
I'll implement a fix to be included in re-linq build 1.13.128 (due
Friday). You can probably get the fix sooner if needed, by checking
out and compiling re-linq's source code from the trunk.
Note, that re-linq will not (for now) be able to partially evaluate
any dynamic expressions. For example, in the following query, re-linq
will not inline x.Member's value as a constant if x.Member is a
dynamic expression (whereas it will inline it if x.Member is an
ordinary expression):
from item in source
where item == x.Member
select item
Regards,
Fabian
> --
> You received this message because you are subscribed to the Google Groups "re-motion Users" group.
> To post to this group, send email to re-moti...@googlegroups.com.
> To unsubscribe from this group, send email to re-motion-use...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/re-motion-users?hl=en.
>
>
public static class DynamicMemberMetadata { public static object GetMember(string name, object instance = null) { throw new UnreachableException(); } public static readonly MethodInfo GetMemberMethod = ExpressionHelper.GetMethodInfo(() => GetMember(null, null));
}
I've just committed the fix I talked about earlier. It avoids the
InvalidOperationException by making re-linq's partial evaluator just
ignore DynamicExpressions (and other .NET 4 expressions).
About your own workaround: If I understand you correctly, your
workaround circumvents the problem by just replacing the dynamic
expression with a "dummy" method call prior to partial evaluation,
right?
That's a good idea, but, as you said yourself, you then need to adapt
partial evaluation to ignore your metadata method. I've got an even
better idea: You could replace the DynamicExpression with a custom
metadata expression (i.e., not a method call that represents your
metadata, but an expression node that represents your metadata), which
re-linq will then know how to handle (and it will never partially
evaluate it). That way you could avoid patching the partial evaluator.
Here's how it should work:
public class DynamicMemberExpression : ExtensionExpression
{
private string _name;
private Expression _instance;
public DynamicMemberExpression (string name, Expression instance = null)
{
_name = name;
_instance = instance;
}
protected override Expression VisitChildren (ExpressionTreeVisitor visitor)
{
var newInstance = visitor.VisitExpression (_instance);
if (newInstance !=_instance)
return new DynamicMemberExpression (_name, newInstance);
else
return this;
}
public override Expression Accept (ExpressionTreeVisitor visitor)
{
var specificVisitor = visitor as IDynamicMemberExpressionVisitor;
if (specificVisitor != null)
return specificVisitor.VisitDynamicMemberExpression (this);
else
return base.Accept (visitor);
}
}
public interface IDynamicMemberExpressionVisitor
{
Expression VisitDynamicMemberExpression (DynamicMemberExpression
dynamicMemberExpression);
}
If you're using a custom expression visitor to translate the
expressions within the QueryModel into your own QueryDescription, just
implement IDynamicMemberExpressionVisitor on it.
Of course, if you don't mind the patching, you can just stick to your
existing solution :)
One more word about how you replace the DynamicExpression with your
method call (or, maybe, my DynamicMemberExpression): re-linq sports a
feature called "expression transformers" that would be nicely suited
to perform that task. Maybe you're already using it; if not, take a
look at this blog post:
"https://www.re-motion.org/blogs/mix/2011/04/29/re-linq-customizability-explained/".
Cheers,
Fabian
Great, let me know if you need any help with my sample.
Regards,
Fabian
On Wed, Nov 2, 2011 at 12:28 PM, Alex Norcliffe