Clean approach to 1-N relationship

Jan 6, 2010 at 12:08 AM

If I have an object and that object is responsible to construct child objects that has .Parent property linking back to its parent, how can I use MEF for this scenario?

I know I can use PartCreator to create the object without referring directly to the container. However, it doesn't have the concept of local container. The best way is to import CompositionContainer?

Jan 6, 2010 at 12:32 AM

What do you mean by local container? What won't PartCreator allow?

Jan 6, 2010 at 2:43 AM

something like HierarchyContainer but local to the current object so that I can inject the current object in without interfering with other instance of Object. For example, I have 5 order screens. Each screen can create its own order detail. Each order detail should have a reference back to its own order.

Jan 6, 2010 at 4:22 AM
Edited Jan 6, 2010 at 4:23 AM

Hierarchical containers are probably the way to go as you'll likely have app-level services you want to share. There are several apporaches you could take each which uses hierarchical containers.

1. Have a ContainerFactory import which has access to the root container. A call to the Create method then gives you back a new container that is automatically parented. Create can optionally accept a catalog, which it will set on the child container.

2. Have a ScopedPartCreator import which has a Create<T> method on it. Calling Create in this case would create a parented contaienr and then resolve T from the child container. For this to work correctly, you would need a way to release the child container once you are done with it. One possible way to do this would be have Create also accept a key and keep a dictionary of containers by key, and then have a corresponding Release method. This way when you are done you call Release(key) which grabs the corresponding container from the dictionary and dispsoes of it.

Glenn

Coordinator
Jan 6, 2010 at 5:41 PM

As far as linking the .Parent property back to the parent object, I think it might be better not to use MEF to handle this part.  The Parent property could be a member of your contract interface, and after the parent creates an object, it would set that object's Parent property.

If you do need to have the parent be satisfied via an import, then you may want to put the parent object into the child container (via the ComposeExportedValue extension method) with a contract name of "Parent" or something.  You would specify the same contract name on the import.

Jan 6, 2010 at 7:33 PM

I have created a system similar to that described in item 2 of Glenn's posting. I created a custom ExportAttribute class with which I can specify the scoping for a particular Export (i.e. that contract "IChild" should be scoped to contract "IParent"). That way I can easily identify which parts need to be available from the child container, and which will be available from the parent container. I also created a custom ExportProvider (derived from CatalogExportProvider) that automatically takes care of figuring out all the exports that are "scope owners", and when one of these exports is requested does the following:

1) Creates a child container

2) Populates it with all the parts that advertised scoping to the scope owner (done using a FilteredExportProvider I run against the parent container's catalog)

3) Pulls the new part from the child container and hands it back to the caller

4) Maintains a dictionary so that when the scope owner is disposed, it disposes its container.

This system seems to work reasonably well, but be prepared that there seems to be a bit of a performance hit for the container creation (~0.3 seconds on my 4 year-old laptop) so it may not work well where there are a lot of scoped containers being created, or the nesting is very deep.

Ron

 

Coordinator
Jan 6, 2010 at 9:05 PM

Container creation should be very cheap, so I think the performance hit you are seeing is probably due to some of the other operations you are performing (perhaps creating the scoped parts).

Jan 6, 2010 at 9:14 PM

natl if all you are doing is supplying a reference of the order to the child controls, then adding Order to the child control contract and setting explicitly makes sense. If you expect there to be more than that and several different services scoped at the level of the order which are shared by nested components then having container scoping is a better path.

Jan 6, 2010 at 11:01 PM

actually my scenario is to injecting dependency at the scope level. There are certain number global services and local services.

Jan 6, 2010 at 11:54 PM

Let me give you with a better example. If you look at web application, you should be able to ask objects/services from different scopes such as Application, Session, Request, etc. It would be nice if we can selectively construct objects in this manner whether it be by customattribute or referring to the child container explicitly.

Jan 16, 2010 at 10:47 PM

Glenn,

I found a good use case example, take a look at http://weblogs.asp.net/seanmcalinden/archive/2010/01/13/custom-ioc-container-for-dependency-injection-with-an-asp-net-mvc-website-usage-example.aspx Over here, you can see that in Mvc, you can bind certain things at the different scope.