Archive for January, 2009

MEF and lifetime

January 30th, 2009

It has been interesting three months working on the lifetime story for MEF. Turned out to be bigger and more complex than any one could anticipate. As I walk you through what has been decided and implemented you may find things too trivial, but actually it was huge as key members in our team wanted something way different. Under this light I really considered the MEF/Lifetime a success as we – the feature crew (Wes and Daniel) – were able to demonstrate clearly the impacts of their proposed changes and how our proposal solved key scenarios.

Here is a summary of the top level decisions:

  • We will continue to support singletons and transients (we renamed them to Shared and NonShared)
  • We will continue to support disposable types (even when IDisposable is not part of the public contract of the service)
  • The container will have the ownership of parts it instantiates (we will not transfer ownership to parts)

You can get the bits from CodePlex, Preview 4 has all the lifetime features implemented and documented.

 

CreationPolicy

We now support three creation policies. They can be specified on the part level – using the CompositionOptionsAttribute – or on the import level, using the ImportAttribute. Both sides need to permissible in order to the dependency be satisfied.

  • Shared: former Singleton. A single instance per lifetime domain (ie, container)
  • NonShared: former Factory. Whenever an export is requested, a new instance is created.
  • Any: defines that the part can function as Shared or NonShared, it would be up to the import side to define. If “Any” is specified on both sides, it will default to Shared.

Container and parts references

The CompositionContainer will not hold references to parts it creates, unless for the following cases:

1. The ComposablePart.RequiresDisposal returns true – which for our default programming will be true only when it wraps an object instance that implements IDisposable

2. The part has one or more imports marked with AllowRecomposition=true. In this case, though, we hold conditional references, which means that while there’s an alive export instance the GC won’t collect the part instance.

3. Shared parts

For all other situations, parts are created, exports gathered and we drop the references leaving everything else to the GC.

One thing to note: if have NonShared disposable parts you might incur in memory bloat. There are two ways to avoid that, described below.

 

Disposing the container

Disposing the container will shutdown parts held (possibly disposing them, and disabling recomposition). Lazy exports wont work anymore. As any disposable type, we haven’t engineered the container to be reusable after being disposed.

 

Scoping containers

You can use container hierarchies in order to create scoped lifetime. For example, a web request is a great candidate to be mapped that way. However, as the container depends on Catalogs you will either have to filter the global catalog – the one that the parent container has access to – or handcraft a new catalog. Using the same catalog on the parent and on the child container won’t make much sense IMHO as then you start to have short lived Singletons.. and this doesn’t feel right to me.

Check the Filtering Catalogs for more information on this.

 

Early release of resources

If you don’t want to use container hierarchies, you can also release an object graph. This is a great solution for scoped operations that you control when it starts and ends.

Just use the method ReleaseExport exposed on the CompositionContainer class. It traverses the parts and its imports releases NonShared parts. It stops in Shared parts as we cannot touch them.

 

Lifetime of parts manually added to the container

When you add an object instance directly to the container you do not transfer its ownership to it – at least not now, we’re discussing and reviewing this behavior. However, adding a part manually will cause composition, so new parts may be created to satisfy your object dependencies. Who own them? The container. MEF is smart enough to shutdown them when you remove that object from the container.

 

Ordering

Due to the fact that we support – to some extend – cycled object graphs, we cannot create a 100% deterministic disposal algorithm. Hence, we do not guarantee disposal ordering and urge you to follow a simple guideline:

“Do not use imports on your dispose method.”

That means, do not use the things your part imported on your implementation of the Dispose method. Why? Because as we do not guarantee ordering, they might have been disposed when you try to use them.

 

Conclusion

It’s been a fun ride. Given the fact that we considered removing support for NonShared, transfer ownership of exports to imports and all sorts of options, I’m absolutely positive that we have made the right choices. I’ve learned that there’s no such thing as the perfect design for complex problems. In that case you have to strive for the right trade-offs and make sure you provide solutions for the key scenarios.

Categories: MEF, MS | Top Of Page | 1 Comment » |

MEFGrid

January 15th, 2009

Daniel managed to create a sample that goes over virtually all features of MEF. Mind blowing, I know. That’s why he’s know as “da man” in the team.

If you’re following MEF you should check it. Make sure you also subscribe to his blog.

Categories: MEF | Top Of Page | No Comments » |

A small excerpt from the IoC Container doc

January 7th, 2009

Twitter followers probably know that I’ve been working on an IoC Container document for my team. It goes over several aspects – including why in my view “DI” is a wrong term and should be banished – from history to features and scenarios. I got permission to release some bits of it in the future. The following however is an excerpt I thought I should share.

Another important aspect of common use of IoC Containers lies on the fact that the components that make up an application play no role in defining or constraining the implementation that can satisfy a dependency. The minimal safety is provided by strongly typed contracts, but it ends there. All binding is left for an external entity – the application host.

Given that the ultimate goal is to reduce coupling and promote reuse, this approach makes a lot of sense as it allows components to be used anywhere, with or without a container.

The component can express what is required or optional using natural OOP idioms. For example, multiple constructors will allow the IoC Container to call the one it can satisfy the most arguments. Also public writable properties are considered optional dependencies for most containers. Note that the container is just playing the role of a user of the class, checking constructor overloads and properties that they can provide values for, absolutely no different from a human interacting with the same class.

By sticking with these natural idioms a class will be naturally decoupled, easy to be reused and easy to be tested. The fact that it also plays well with IoC Containers is a consequence of the decoupling exercise, and should not be misunderstood as the main driver.

Categories: IoC, MS | Top Of Page | 7 Comments » |

Some Castle related news

January 5th, 2009

During the holiday – and between Wow quests and dungeons – I’ve managed to apply a bunch of patches and to fix some outstanding bugs on the Components and Windsor projects.

Another interesting accomplishment is some contributions finally made in and Castle.Core, Castle.MicroKernel and Castle.Windsor are now Silverlight ready.

Last but not least, I recently applied a patch that made Castle.DynamicProxy 2 also available for Silverlight.

The pending items now are:

- Fix the build so the bits targeting SL will be correctly build and made available through our build server

- Change Windsor to use the SL version of DynProxy.

Thanks for all the patches, people. Keep them coming! :-)