Injecting DynamicMetaObject from "outside"

Apr 29, 2009 at 6:38 AM
Hello there,

I'm trying to figure out if it is possible to "make an object dynamic" without implementing the IDynamicMetaObjectProvider interface on it. My problem is that I'm trying to add dynamic capabilities to a type without modifying assembly that houses the type. I've looked at the DLR sources but nothing obvious jumped out at me.
I'm looking for some way to register at runtime as meta object provider for type X.

Is this possible?

Thanks,
Albert
Apr 29, 2009 at 12:30 PM
This is not currently possible. Languages like Python and Ruby can treat existing static types dynamically because they control all method binding, but they don't use IDMOP to do this.  If I were going to implement this kind of feature, I'd probably want to do it by modifying the CLR to do JVM-style interface injection instead of creating a DLR-specific mechanism -- but I have no idea whether the CLR team is even considering such a feature.

If you tell us a little more about what you're trying to accomplish, we may be able to suggest another approach.
Apr 29, 2009 at 1:28 PM
I actually have this same issue in my DLR implementation.

I have many pre-existing domain types for which implementing IDMOP is not possible, but for which I absolutely do want dynamic dispatch behavior. I get around this with custom logic in my binders, but it's a clunky and brittle solution.

I think an interesting pattern for this would be registration of a surrogate type to handle the dispatch on behalf of the other type... something like the way serialization surrogates work for non-serializable CLR types. I suppose there are some interoperability challenges there (probably need to register with scriptruntime not langcontext) but reducing frictions like this at the DLR/non-DLR boundary is critical to wide adoption, I think.

My previous post about enabling dynamic dispatch on internal types (particularly for application scripting scenarios) is another example of this "real world" friction that I hope will be addressed, eventually.

Apr 29, 2009 at 4:07 PM
Hi Curt,

Thanks for the response. Here are some more details: We have a large application with a 3rd party ecosystem. We have a object model that we expose to .NET clients. One of the crucial types in the object model is called "ObjectId". Many features of the object model are accessible to the client applications by the following pattern:

ObjectId id = GetAnObjectIdFromSomewhere();
obj = id.Open()
obj.DoSomething()
obj.Close()

I find that if I implement IDynamicMetaObjectProvider on ObjectId then I can enable this simpler code for clients:

dynamic id = GetAnObjectIdFromSomewhere();
id.DoSomething()

This is great! The problem is that IDynmicMetaObjectProvider currently sits in some Microsoft.* assembly but it will move some System.* assembly in .NET 4.0. I do not want to publish 2 versions of our assembly because it will create huge confusion in our ecosystem. I want to have a "preview" version of this simplified programming model that clients of the existing installed base could use in conjuction with the open source DLR. They would reference our "scripting" assembly which in turn would inject itself as an IDynamicMetaObjectProvider for ObjectId. In the long run, I do not mind taking a dependency on the System.* assembly that will house IDynamicMetaObjectProvider. I just need some short term solution so that I can target the open source DLR without taking a dependency on it in our published object model.
Apr 29, 2009 at 4:09 PM
One more thing: Strictly speaking you already do this. You treat COM objects as special case. It would be nice if there was some general extensibility point that both COM objects and other 3rd parties could use.
Coordinator
Apr 29, 2009 at 4:41 PM

This might not work for you but one possibility might be due re-build the DLR yourself and update DynamicMetaObject.Create to support some custom mechanism that you could support in your object model. 

From: szilvaa [mailto:notifications@codeplex.com]
Sent: Wednesday, April 29, 2009 8:07 AM
To: Dino Viehland
Subject: Re: Injecting DynamicMetaObject from "outside" [dlr:54794]

From: szilvaa

Hi Curt,

Thanks for the response. Here are some more details: We have a large application with a 3rd party ecosystem. We have a object model that we expose to .NET clients. One of the crucial types in the object model is called "ObjectId". Many features of the object model are accessible to the client applications by the following pattern:

ObjectId id = GetAnObjectIdFromSomewhere();
obj = id.Open()
obj.DoSomething()
obj.Close()

I find that if I implement IDynamicMetaObjectProvider on ObjectId then I can enable this simpler code for clients:

dynamic id = GetAnObjectIdFromSomewhere();
id.DoSomething()

This is great! The problem is that IDynmicMetaObjectProvider currently sits in some Microsoft.* assembly but it will move some System.* assembly in .NET 4.0. I do not want to publish 2 versions of our assembly because it will create huge confusion in our ecosystem. I want to have a "preview" version of this simplified programming model that clients of the existing installed base could use in conjuction with the open source DLR. They would reference our "scripting" assembly which in turn would inject itself as an IDynamicMetaObjectProvider for ObjectId. In the long run, I do not mind taking a dependency on the System.* assembly that will house IDynamicMetaObjectProvider. I just need some short term solution so that I can target the open source DLR without taking a dependency on it in our published object model.

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

Coordinator
Apr 29, 2009 at 4:45 PM

We’ve actually gone around and around on having a registration mechanism so that other people can provide the DynamicMetaObject’s for objects.  The problem we’ve run into is one of scoping this to some reasonable level.  The only way we can really scope this today would be to make it per-app domain.  Then you start getting into what happens when someone registers for the same type, how do ensure that languages aren’t getting broken by the registration, etc…  Global registration is perilous and that’s the reason why we haven’t done something like this – of course it does keep coming up over and over again so I’m sure we’d be interested in hearing solutions we haven’t yet considered J

From: szilvaa [mailto:notifications@codeplex.com]
Sent: Wednesday, April 29, 2009 8:10 AM
To: Dino Viehland
Subject: Re: Injecting DynamicMetaObject from "outside" [dlr:54794]

From: szilvaa

One more thing: Strictly speaking you already do this. You treat COM objects as special case. It would be nice if there was some general extensibility point that both COM objects and other 3rd parties could use.

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

Apr 29, 2009 at 5:18 PM
The callsite should be able to decide what provider they want to work with. So if there are multiple providers for the same object then you would choose based on the identity of the calling code. The calling code would expresss its preference by registering the provider itself. So we have the following players:
1. Client assemblies (client1, client2)
2. Provider assemblies (provider1, provider2)
3. DLR (dlr)
4. Shared type (XmlNode)

client1 wants to work with provider1 and client2 wants to work with provider2. client1 is responsible for calling dlr.RegisterProvider(provider1.ProviderForXmlNode) before reaching any callsites where it needs the provider. From then on the DLR will use provider1 in all callsites of client1. When client2 gets control it is responsible for calling dlr.RegisterProvider(provider2.ProviderForXmlNode ) and the DLR will ensure that all callsites of client2 will use this provider. Obviously, if no call is made to dlr.RegisterProvider then everything works as it does today.

Admittedly, I have extremely little experience with dynamic languages or the DLR so this proposal is likely wrong. It is based on how I would like this to work.

Apr 29, 2009 at 6:50 PM
This would be great... could hang a virtual member on LanguageContext to expose list of providers (default impl. returns empty list).

Can't be that big a deal to make call site binders aware of this.


Coordinator
Apr 29, 2009 at 9:33 PM

How would he b able to share those with any other code, wouldn’t his DMOs be totally different types in the .NET eyes?

From: dinov [mailto:notifications@codeplex.com]
Sent: Wednesday, April 29, 2009 8:42 AM
To: Bill Chiles
Subject: Re: Injecting DynamicMetaObject from "outside" [dlr:54794]

From: dinov

This might not work for you but one possibility might be due re-build the DLR yourself and update DynamicMetaObject.Create to support some custom mechanism that you could support in your object model.

From: szilvaa [mailto:notifications@codeplex.com]
Sent: Wednesday, April 29, 2009 8:07 AM
To: Dino Viehland
Subject: Re: Injecting DynamicMetaObject from "outside" [dlr:54794]

From: szilvaa

Hi Curt,

Thanks for the response. Here are some more details: We have a large application with a 3rd party ecosystem. We have a object model that we expose to .NET clients. One of the crucial types in the object model is called "ObjectId". Many features of the object model are accessible to the client applications by the following pattern:

ObjectId id = GetAnObjectIdFromSomewhere();
obj = id.Open()
obj.DoSomething()
obj.Close()

I find that if I implement IDynamicMetaObjectProvider on ObjectId then I can enable this simpler code for clients:

dynamic id = GetAnObjectIdFromSomewhere();
id.DoSomething()

This is great! The problem is that IDynmicMetaObjectProvider currently sits in some Microsoft.* assembly but it will move some System.* assembly in .NET 4.0. I do not want to publish 2 versions of our assembly because it will create huge confusion in our ecosystem. I want to have a "preview" version of this simplified programming model that clients of the existing installed base could use in conjuction with the open source DLR. They would reference our "scripting" assembly which in turn would inject itself as an IDynamicMetaObjectProvider for ObjectId. In the long run, I do not mind taking a dependency on the System.* assembly that will house IDynamicMetaObjectProvider. I just need some short term solution so that I can target the open source DLR without taking a dependency on it in our published object model.

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

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