Expression.Dynamic

Jun 15, 2010 at 5:33 AM

Hi there,

I have an Expression which looks a bit like this:

		Expression<Func<TEntity, TRelated>> x = (entity) => entity.SomeRelatedObject;

I also have a class DomainObject<TEntity> which is a IDynamicMetaObjectProvider which would return a DomainObject<TRelated> when the same property is accessed through the dynamic keyword.
It basically gets the RelatedObject from the TEntity and wraps it in a DomainObject.
i.e.

		var x = ((dynamic)myDomainObject).SomeRelatedObject; // this gives me back DomainObject<TRelated> object

 

I would like to have a method within my DomainObject<TEntity> class which takes in the Expression above and gets the related object as if the call is made using the dynamic keyword.
i.e.

		public DomainObject<TRelated> GetRelatedObject<TRelated>(Expression<Func<T, TRelated>> expression)
		{
			var lambda = (LambdaExpression)new SomeVisitor<T, TRelated>().Visit(expression);			
			return (DomainObject<TRelated>)lambda.Compile().DynamicInvoke(this);			
		}

I assume this can be achieved by overriding the VisitMember and substituting the MemberExpression with a DynamicExpression but I couldn't find any examples of how to use Expression.Dynamic or Expression.MakeDynamic.

My questions are:
1. Does the above make sense?
2. Can anyone please show me an example of how to construct a DynamicExpression for the above?

Any help would be greatly appreciated.

Many thanks,

Ted

 

 

Coordinator
Jun 15, 2010 at 5:04 PM

First off let me say this isn’t going to perform very well – the Compile() call is expensive and DynamicInovke is also expensive (although much less so). Ideally you’d have some caching strategy around this and then it’d be fine…

That being said the easiest thing to do is to re-use the C# binder such as:

using Microsoft.CSharp.RuntimeBinder;

var binder = Binder.GetMember(CSharpBinderFlags.None, "SomeRelatedObject", typeof(XX), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));

You can then do Expression.Dynamic(binder, new [] { obj }); where obj is the expression for the object.

You can also create your own binder – you can do this by subclassing GetMemberBinder. Because you’re talking to an IDMOP you don’t really need much in the way of a fallback expression so you could just return an expression which throws an exception. So long as you’re not trying to get a member defined via .NET metadata that’ll work fine.

Or you could create your own binder and use the DefaultBinder class in the DLR outer layer to implement the .NET reflection which needs to happen for talking to normal objects.

From: tburhan [mailto:notifications@codeplex.com]
Sent: Monday, June 14, 2010 10:34 PM
To: Dino Viehland
Subject: Expression.Dynamic [dlr:216036]

From: tburhan

Hi there,

I have an Expression which looks a bit like this:

              Expression<Func<TEntity, TRelated>> x = (entity) => entity.SomeRelatedObject;

I also have a class DomainObject<TEntity> which is a IDynamicMetaObjectProvider which would return a DomainObject<TRelated> when the same property is accessed through the dynamic keyword.
It basically gets the RelatedObject from the TEntity and wraps it in a DomainObject.
i.e.

              var x = ((dynamic)myDomainObject).SomeRelatedObject; // this gives me back DomainObject<TRelated> object

I would like to have a method within my DomainObject<TEntity> class which takes in the Expression above and gets the related object as if the call is made using the dynamic keyword.
i.e.

              public DomainObject<TRelated> GetRelatedObject<TRelated>(Expression<Func<T, TRelated>> expression)
              {
                      var lambda = (LambdaExpression)new SomeVisitor<T, TRelated>().Visit(expression);                       
                      return (DomainObject<TRelated>)lambda.Compile().DynamicInvoke(this);          
              }
 

I assume this can be achieved by overriding the VisitMember and substituting the MemberExpression with a DynamicExpression but I couldn't find any examples of how to use Expression.Dynamic or Expression.MakeDynamic.

My questions are:
1. Does the above make sense?
2. Can anyone please show me an example of how to construct a DynamicExpression for the above?

Any help would be greatly appreciated.

Many thanks,

Ted

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Jun 16, 2010 at 3:57 AM

Thanks for that, Binder.GetMember is really I was looking for.