Welcome to MSDN Blogs Sign in | Join | Help
Appearance on .NET Rocks!

This week I took some time out to talk to Richard and Carl on .NET Rocks! about Autofac, MEF and component-oriented software in general.

If you have any questions about material from the show, please feel free to post them in the comments.

Posted Friday, May 29, 2009 6:55 PM by niblumha | 2 Comments

State Machines in Domain Models

I was reminded today of Stateless, a little project that I’m quite fond of.

Stateless is a hierarchical state machine framework based on Simple State Machine for Boo, but configured using C# 3.0.

When I announced Stateless last year, I hardly even explained its purpose, let alone its tongue-in-cheek name. I think I owe it a better start in life!

If you’re doing heavy duty state-machine based programming (writing parsers, radiotherapy machines or flight control systems) then Stateless is probably not what you’re looking for.

If you’re doing domain-driven design, and anxious about the ugly nested ‘if’ and ‘switch’ statements building up around _state variables, Stateless can help.

State-based behaviour is awkward because despite careful programming, it is difficult to see how the states relate to each other. Adding and removing states is error-prone, repetition creeps in, and refactoring gets tricky.

There’s more than one way out. The State pattern can be one very elegant solution.

Another solution that works nicely is to create a declarative model of the states, transitions and associated actions, and have a state machine framework ‘run’ it for you. This is the approach enabled by Stateless.

image

The Telephone Call state chart is broken down into the following states and triggers:

image

You can use any types to represent states and triggers, but enumerations are convenient.

After creating an instance of StateMachine, each state is configured independently. Configuration for a state revolves around the triggers that the state can accept, the transitions that these triggers will cause (to new states) and the actions that will be performed when entering or leaving a state.

image

Once the state machine has been configured, the triggers can be ‘fired’. The side-effects from firing triggers drive the program.

image

You might wonder how this fits into a domain model. StateMachine certainly doesn’t belong on the public surface area of your domain model classes. It’s an implementation detail – like, for example, StringBuilder or Regex.

image

Users of the class interact with the state machine indirectly, by calling public methods on the domain object.

image

The state machine is configured to call two methods when entering and leaving the Connected state (see the configuration above.)

image

Stateless does all of the heavy lifting. For example, the state machine understands that because OnHold is a sub-state of Connected, the Connected entry/exit actions aren’t called when moving between these two states.

Now for a justification of the silly name…

Notice the way that the _state field belongs to the PhoneCall object, rather than the state machine? This allows the field to be easily mapped to a database column by NHibernate or your ORM of choice. The state machine reads and writes the _state value using the pair of lambdas provided to its constructor. In that sense you can almost say that the state machine itself is ‘stateless’. Almost.

There’s some more basic documentation and a source download at the site. I hope you’ll try Stateless and be pleasantly surprised by how expressive it can make your code. Search your domain model for “State” or “Status” and see what Stateless can do!

This post also comes with a challenge: Stateless is fairly simple and very hackable - if you’re a fluent-interface aficionado and think you can improve the configuration API, join the project!

Posted Thursday, April 16, 2009 7:52 AM by niblumha | 7 Comments

Filed under: ,

MEF: Dependencies are Queries?

Start to schematically represent any component system and you’re likely to come up with a diagram like:

image

So what do the dependency and the service actually mean?

In most implementations, each is associated with a key:

image

Here the Screen Renderer component needs the Typesetter service, which the Fast Typesetter component can provide.

Dependency resolution is a done by matching keys – resolving the Screen Renderer’s dependency boils down to doing a dictionary lookup with Typesetter as the key, to find the Fast Typesetter implementation.

This is the case whether the dependencies are expressed as strings, types, or some combination of the two.

While this model is very powerful and can be taken a long way, ‘open’ systems can benefit from an alternative approach.

Imagine a system in which multiple renderers and typesetters exist, each with distinct capabilities:

image

The dependencies above are no longer evaluated using simple equality comparisons.

On the right, the capabilities of each component are represented as structured data: the service provided, plus a collection of key-value pairs bearing more detailed information. Together these are a service definition.

On the left, the dependencies of each component are represented as predicates over the possible service definitions. The predicate evaluates to true if the service definition can satisfy the dependencies.

So, the Print Renderer’s requirements, { Quality == High }, are true when evaluated against the Accurate Typesetter’s service definition, and false when executed against the Fast Typesetter’s.

In effect, components express their dependencies as queries over the entire set of available services.

To get an idea of where the power of this technique comes from, consider the way the example will compose: the Screen Renderer gets a fast Typesetter and the Print Renderer gets an accurate one. In a system with a better Typesetter – one that is both fast and accurate – a single Typesetter implementation could fulfill both dependencies.

Constraints aren’t just limited to equality comparisons either – if speed is expressed in characters per second, the Screen Renderer could specify { Speed > 500 }.

If you haven’t guessed already, this is the model that the MEF Primitives use. The service definitions are exposed with the type ExportDefinition. The predicate for testing ExportDefinitions for suitability is encoded in ImportDefinition.Constraint.

image

One of the constraints in the example might be expressed as:

image 

The system is elegant, but there are a few things to be aware of. The first that comes to mind is how the constraint is Boolean, so ‘falling back’ to a slow Typesetter when no fast one is available means expressing two separate constraints

Because ImportDefinition.Constraint is a Linq expression, and thanks to some special-case logic, MEF is able to resolve many dependencies without doing the linear scan that the query implies. This is only the case when constraints take the typical forms expressible in MEF’s Attributed Programming Model. Arbitrary constraints can result in a linear scan (although the way is clear to optimizing these in the future.)

One other interesting note – it is technically possible to transform an import constraint into a format that could be evaluated by a database-backed Linq provider… If for some reason you’d like to do that :)

You might be wondering why code snippets like the predicate above don’t appear in the MEF examples you typically see. The answer is that this is the key to understanding programming models. A programming model, in the MEF sense, translates some easy-to-type format like the Import and Export attributes, into constraints under-the-hood.

Constraint-based dependency resolution is one of the foundations that future versions of MEF will build upon.

Posted Thursday, April 16, 2009 12:01 AM by niblumha | 7 Comments

Filed under:

Hosting MEF Extensions in an IoC Container

There has been a lot of discussion among IoC container users about the similarities between MEF and IoC containers. Most of this has been addressing the question - “should MEF and an IoC container be used in the same app, or are they exclusive?”

One possible answer to this question is outlined below. It isn’t by any means the definitive answer, but if these are technologies you find interesting, hopefully this article will give you plenty of food for thought.

An IoC container is not required in order to use MEF. Unless you’re building or using an IoC container, this article probably won’t apply to you :).

Defining Extensibility Points

The Managed Extensibility Framework (MEF) in .NET 4.0 introduces a standard model for defining and consuming application extensibility points.

Central to this model is the ComposablePartCatalog type and its subclasses:

image

AssemblyCatalog and DirectoryCatalog can read set of attributes for defining extensions:

image

Here Export marks the Square class as an extension providing the IShape contract.

.NET 4.0 also introduces a class for assembling extensions into complete object graphs. This class is called CompositionContainer:

image

The role that CompositionContainer plays in a .NET 4.0 application is very similar to the role and IoC container might play in a .NET application today.

This has raised a lot of interest among IoC container users, who want to know how they can take advantage of MEF in their applications. Should CompositionContainer, for instance, replace their current IoC container, or can the two containers work together?

The answer to this question is trickier than it seems, because there are substantial problems associated with having more than one container in an IoC-driven application:

  1. How do the containers mutually decide that an instance’s lifetime is over?
  2. How is context maintained, so that the correct type gets its correct dependencies even when they’re provided by the other container?
  3. If the graph building operation moves backwards and forwards between two containers, how can circular dependencies be detected (without StackOverflowException!)
  4. How can diagnostic messages provide the ‘full picture’ when each container only knows about a portion of the graph being constructed?

(Some of this is a general problem with composing frameworks in general, and is felt today by IoC container users integrating with UI frameworks in particular. It might be called ‘competing for control’.)

The good news is that there is at least one way to get some benefits of MEF in an application that uses an IoC container without using two containers.

MEF/IoC Container Roles

Although similar in many respects, the goals of MEF and IoC containers are different, and this gives each technology unique strengths.

MEF is built for open systems – scenarios in which the complete set of components that make up an application is defined at execution-time.

This means that MEF:

  • supports self-describing components that carry all of the information required to use them
  • makes strong guarantees about how components will be loaded and manipulated, regardless of the execution environment
  • includes robust tools for finding and loading components in different media
  • allows components to be queried and inspected without necessarily loading or executing them

MEF is also part of the .NET Framework, so developers can learn how to use it once and then apply these skills in all MEF-enabled applications.

IoC containers, on the other hand, have focused on highly-decoupled yet primarily closed systems. I take the definition of ‘closed’ to mean that all application components are present during integration and testing.

This makes typical IoC containers:

  • highly customizable to suit the internal architecture of a specific application
  • extremely flexible in the criteria for what can be used as a component
  • easy to wrap around existing frameworks and legacy code

These requirements lead in different directions when designing composition technologies, but appear together in some applications.

Both MEF and typical IoC containers are flexible enough to fit to most scenarios; however, their ideal roles might be:

  • define third-party extension points using MEF
  • locate and load these extensions using MEF
  • structure and manage the host application’s fixed architecture using an IoC container

Hosting MEF Catalogs

There are several approaches to integrating MEF and IoC containers. The one described here is probably the most powerful/complete/complex, those interested in other perspectives might start with this recent article by Patrik Hägne.

Most IoC containers, and MEF, use a layered architecture:

image

MEF’s composition functionality is wrapped up in CompositionContainer, and its component model in ComposablePartDefinition and related types like ComposablePartCatalog.

Autofac, an open-source IoC container [disclaimer: written by the author] follows the same typical pattern, using different types: Container and IComponentRegistration. (Funq, Linfu, Ninject, Windsor, Spring.NET, StructureMap and Unity use similar abstractions.)

Autofac and MEF used in the same application, without any integration, look like:

image

The crossed-out arrow in the centre reflects the barrier that we’re trying to cross: the Autofac composition process won’t include components that are composed by MEF, and vice-versa.

This kind of cross-over is frequently desirable, e.g.:

  • Application components invoke extensions
  • Extensions need to access services provided by the host application

The diagram below shows how this issue can be addressed without introducing the ‘two container’ problem:

image

Rather than hosting the MEF components in a separate container, an adapter is used so that the MEF components are presented to the Autofac container as Autofac components.

The adapter allows MEF and Autofac components to participate in the composition process at the same time – each can have dependencies satisfied by the other.

The IoC container is chosen as the ‘host’ because:

  • The application components are the ones most likely to integrate deeply into the container, and since they’re IoC container components it makes sense that they are hosted in the IoC container
  • IoC containers don’t provide as robust a component mode as MEF does, so hosting components from any particular container in MEF is difficult

So how does this look in practice?

Example Application: IoC and MEF

You can download a very contrived example that demonstrates many of the moving parts here. This is not production quality design, so please don’t flame me for it :)

The example is a task scheduler – perhaps you can imagine it running as a Windows service. It has two extension points: the tasks that will be run, and an output device to which notification messages can be sent.

The extension points are regular MEF parts.

The tasks export an interface and specify the interval at which they should be invoked via metadata attributes:

image

Notification services are similar, exporting the IMessageNotifier interface:

image

The container is created and Autofac services registered as usual:

image

An extension method, RegisterCatalog(), allows a MEF DirectoryCatalog to be supplied to the container:

image

Note the list of services that will be imported from the catalog into the application. Parts can still export and import other contracts, but these won’t be available to Autofac components. This keeps the extensibility points of the application clearly defined.

Similarly, Autofac services have to be explicitly marked when they will be provided to MEF components:

image

There’s an example of an Autofac component consuming a mix of Autofac and MEF services:

image

As well as MEF components consuming Autofac services:

image

Everything feels natural, although there are a few awkward issues surrounding the consumption of MEF metadata in Autofac services. These should go away once the MEF Export type is a framework type (it won’t feel so leaky to inject exports into Autofac components.)

Limitations

MEF defines how individual components will be manipulated, not how they will be assembled into complete object graphs.

This makes sense for open systems, because regardless of how components are packaged, they should not make assumptions about their host environment beyond the contracts that their immediate dependencies supply.

When designing components that can be used in multiple applications, each component needs to be treated independently. MEF discourages thinking about catalogs of components as subsystems with a fixed configuration.

The biggest side-effect of these decisions is that while MEF components behave consistently whether hosted in MEF or another container, groups of components will probably behave differently.

MEF’s container also offers a different set of features from the typical IoC container – these may be sorely missed in highly-extensible applications, so if high extensibility is the goal the MEF container alone is likely a better choice.

Status

It will be some time before there is much empirical data on the benefits and pitfalls of this technique – YMMV, so be sure to carefully evaluate your needs before starting down this path. Experimental is probably the appropriate tag!

.NET 4.0 and MEF are not yet released, so these techniques may not even apply to the production version.

There is a whitepaper on the MEF site describing some of the technical requirements of the approach.

Some notes on the Autofac adapter are available on the Autofac wiki.

Posted Monday, March 16, 2009 11:14 PM by niblumha | 1 Comments

Filed under: ,

IoC Open Space at ALT.NET Seattle

We had a great little open discussion on building IoC-driven apps today at ALT.NET Seattle.

A handful of good points came up:

  • Building aggregate object graphs for the UI layer is giving people headaches
  • Dynamic instantiation patterns like 'injected context' and 'generated context adapter' are starting to gain more recognition as basic buildling blocks
  • Service locators can be a useful step in the process of refactoring-to-IoC (seems like there is some work to be done in developing a body of knowledge in this area)
  • The time is right for some better tooling, e.g. dependency graph exploration

Thanks everyone who showed up and got involved. (Extra thanks to Glenn Block for setting up the session - kudos!)

Posted Sunday, March 01, 2009 12:08 AM by niblumha | 1 Comments

Filed under:

IoC on Silverlight

A number of IoC containers have Silverlight versions - Ninject and Unity especially seem to have healthy Silverlight offerings. Silverlight 2.0 is a variant of the .NET runtime, so this isn't too surprising.

Thanks to Tyson Stolarski and Rinat Abdullin, Autofac recently joined their ranks with a Silverlight-compatible build. (This one is hot off the press, so test it thoroughly before you set out to build anything mission-critical :))

MEF hasn't released any concrete plans for Silverlight, but experimenters can probably coerce the Codeplex source into a compatible build by hacking the .csproj file.

If you're reading this blog and use IoC on Silverlight in one form or another:

  • What have your experiences been like?
  • Do you use IoC in the UI, the 'back-end' or both?
  • Does loose coupling/runtime composition get in the way of XAML-based designers?

I'd love to hear your thoughts!

Posted Sunday, January 04, 2009 5:48 PM by niblumha | 2 Comments

Filed under: , ,

Declarative Context Adapters

The first post in this series introduced the problem of accessing IoC container features dynamically.

We brushed over two common patterns:

  • Global Container (or Static Service Locator)
  • Injected Context

Before we move on from this topic, I'd like to look at one more pattern in this theme that may not be in common use, but deserves some attention anyway.

This pattern I've labeled Declarative Context Adapter, and it builds on the strengths of Injected Context while moving from imperative implementation to declarative configuration.

Problem

After composition, a component requires dynamic access to features of the container that hosts it (the context.)

Commonly, this involves dynamically creating or locating instances from the container (e.g. see ControllerProvider in this article.)

Solution

  • Provide a domain-specific interface to the required functionality.
  • Describe how this interface should interact with the container using metadata or configuration.
  • A compliant implementation is supplied based on the metadata.

Example

One example of a Declarative Context Adapter is the generated factories feature of Autofac.

This feature uses .NET delegate types as the 'domain-specific interfaces'. The Shareholding.Factory delegate type below plays this role:

image

In this example, we want invocations of the Factory delegate to return instances of the Shareholding class created and wired up by the container. This example is a bit contrived, since usually there is some abstraction involved, but hey, it is just an example :)

The ContainerBuilder's method-chaining API allows the mapping between the delegate to the container's Resolve() method to be specified:

image

This is specified via the RegisterGeneratedFactory() method.

The only declarative configuration in this example apart from the delegate type itself, is the TypedService parameter that tells Autofac which service from the container should be returned whenever the delegate is invoked.

(Additional configuration options can describe parameter mappings for the delegate parameters, however these aren't available in the current release builds.)

Other components that need to instantiate Shareholdings can now have instances of Shareholding.Factory injected into them.

Discussion

To call this technique a 'pattern' is a bit premature, since the Autofac feature is the only implementation you can put your hands on.

The same functionality could  be implemented on different containers, perhaps via AOP. It would also be preferable to support interfaces as well as delegate types.

While the examples have been related to instantiation or service lookup, context adapters could be defined for other container features like lifetime management or even component registration. Anywhere that Injected Context is used, it should be possible to generate a configuration-driven alternative.

Source Code

The tiny example from above can be downloaded here if you'd like to experiment with it.

Posted Sunday, January 04, 2009 4:59 PM by niblumha | 2 Comments

Explicit Context Dependencies

As a follow up from my last post about Global Container vs. Injected Context, I would like to share this snippet from Component Software, which casts the difference between the two approaches in another light:

"A software component is a unit of composition with contractually specified interfaces and explicit context dependencies only. ..."

Under this definition, the ControllerProvider based upon an Injected Context is a component, because it publishes its (admittedly broad) context dependency explicitly, via its constructor parameter.

BadControllerProvider, based upon a Global Container, is not a component under this definition because its dependency on the global container is not explicit (you need to have source code in order to find it.)

In my opinion, the distinction is significant because "components" and "wiring" are a higher-level abstraction than "classes" and "references".

In composite applications, an architecture will be more robust and easier to understand if these layers of abstraction are respected, and not tangled up in classes like BadControllerProvider.

(Component Software is a very worthwhile read and contains a lot of relevant material for those interested in IoC containers and other composition technologies. Clemens Szyperski is a mentor and highly influential voice for the MEF team.)

Posted Monday, December 29, 2008 6:34 PM by niblumha | 1 Comments

Container-Managed Application Design, Prelude: Where does the Container Belong?

There is surprisingly little information out there in cyberspace on how IoC containers should fit into application architectures.

In parallel with my MEF/Ruby series, I'm going to discuss some of the principles that I believe should be applied to "container-managed" application design.

The Enigmatic Ideal

In the world of systems built using dependency injection, you hear plenty of mysterious statements like:

“Except for when bootstrapping, don’t access the container directly!”

This kind of thing caused me to scratch my head for the best part of a year before I finally caught on to what was meant.

Basic Mental Models

When confronted with the task of designing an application around an IoC container, the place that the container sits in that architecture usually seems to be influenced by the designer's mental model of what, exactly, an IoC container is.

Model 1: a Dictionary of Services

The dictionary or associative array is one of the first constructs we learn about in software engineering. It is easy to see the analogy between a dictionary and an IoC container that composes objects using dependency injection:

image

Maps to:

image

All that appears to differ is:

  • Some fancy new terms ‘register’ and ‘resolve’ are used, instead of indexer access
  • The logger is created via reflection, saving some typing and configuration code in the case of inter-dependencies

If you come onto a project with established usage of a dependency injection container and had to figure out how to write the code you need to interact with the rest of the system, chances are this is the first mental model you’ll apply.

Model 2: an Abstract new() Operator

Dependency injection containers are often praised for eliminating implementation type dependencies. Going back to our example, we’ve made our request for an ILogger independent of the implementation type that provides it (ConsoleLogger in this case.)

Web frameworks like Monorail and ASP.NET MVC use our dependency injection container to create Controller instances in a similar way.

Perhaps it makes more sense to think of the container as an abstract new() operator?

image

Becomes:

image

Here our container usage has not only abstracted away the concrete type of our MailTransport but also taken care of configuring its Host property. (Configuration must be a feature of our abstract new() operator since the configuration parameters on an instance depend on its concrete type rather than the service it provides.)

Design Outcome: the Global Container

Following either of these mental models encourages you to think about the container as something you retrieve things from. Even the name 'container' pushes us in this direction.

From this perspective, there isn't much of a challenge in the application architecture design assignment!

We'll just create a static property Container on a class, say, Global and get instances from it using Global.Container.Resolve<MyService>().

Easy!

image

This snippet should be familiar as a pattern with another name: the static Service Locator.

Problems with the Global Container as a Service Locator

There are good reasons why this pattern can rightly be called an anti-pattern:

Fragility. The container acts like a bucket of global variables. All of the robustness that is achieved by forcing components to publicly declare dependencies is lost. Unexpected dependencies can appear between seemingly unrelated parts of an application, complicating maintenance.

Reduced Composability. When dependencies are injected, the container can be configured to provide different implementations to different consumers. This is often necessary when combining components that were built independently. When dependencies are retrieved from a global container, the container does not know the identity of the requestor, and is forced to return the same implementation every time.

Limited Reuse. Where the global container resides can limit the reusability of components that depend on it. Migrating components to a WPF application will require code changes if they depend on the global container attached to the HttpApplication class.

Implementation Issues. Concurrency, re-entrancy, circular reference detection, and component lifetime management are much harder/messier in a global container based solution.

Resumption of Control: Generally speaking, these issues arise because calling directly into a global container is a resumption of control. In a container-managed application, the container is given the responsibility of getting the right instances into the right places in order for work to be done. Calling into a global container takes over some of this responsibility in a much less manageable way.

Sometimes, because of the design decisions made in many current-generation frameworks, the Global Container is a necessity, but in order to advance the state of software engineering we need to look beyond this.

Thinking Inside the Box

The mental models listed earlier should have rung some alarm bells:

The container is a dictionary of services? Hang on! If I ask for the same service twice, why do I sometimes get different instances?

Good question. It is easy to configure a dependency injection container to return a new instance of the ConsoleLogger each time one is resolved. Not very dictionary-like, is it?

So the container is really an abstract new operator? Wait! If I sometimes get the same shared instance back, when can I Dispose() it?

These two models aren't even compatible. Sometimes the container hands out new instances, but sometimes what comes back from a call to resolve is a singleton, or an instance that will be shared within some kind of context like the current transaction.

So things are now confusing: who owns these instances, and where do they ‘live’?

Revised Mental Model: An Interconnected System of Objects

Here’s the problem: look at the example on the Autofac homepage. It shows how Register() and Resolve() are used in Autofac. This is a pretty common kind of introductory example to dependency injection. Notice what’s missing?

The most important classes in this example are not ContainerBuilder or Container. From an application architecture perspective, we need to see the Straight6TwinTurbo and Car classes!

The resolve operation is just a way of finding an entry point into a self-contained system.

The entire application resides within the container. There is no ‘outside’ except for whatever entry point gets the ball rolling. An understanding of IoC from this perspective does not revolve around its external APIs like Register() and Resolve().

image

Using this model, the container to gets component instances to the right place at the right time, and application design re-focuses on the implementation of the components themselves.

Design Outcome: Injected Context

This new perspective on the world leaves us with a challenge when implementing our revised IControllerProvider. This service needs to return (potentially) new, parameterised instances of the Controller type.

The solution, commonly implemented in applications today, is to allow the container to provide context to our controller provider:

image

We assume here that ControllerProvider is itself hosted within the container. IContext is an interface that Autofac automatically provides to any components that require it. You can create and use an equivalent interface in any other popular IoC container (there's a MEF example linked from below.)

IContext provides the instance resolution features of the container to the application, but in a controlled manner. The object implementing IContext provides the container's services, but may not be the container itself.

Because this pattern gives the container or application developer an opportunity to customise or proxy the IContext implementation handed out to any particular component, most of the problems associated with a Global Container are mitigated.

Container-Managed Application Design

If you feel like this article and its explanations are somewhat incomplete, you're right. As the title of this post suggests, it is an introduction to a series on the topic. I don't have all the answers, and I don't even have all the questions, so the installments may come in fits and starts. Nevertheless, if you're out to design robust architectures that make use of an component-based composition technology there should be something of interest for you.

I hope this article has whet your appetite!

Sample Code

The sample code, based on MEF preview 3, is very, very rough, and is really only worth consulting if you need to step through some running code in order to clarify the concepts in this article.

Posted Saturday, December 27, 2008 12:32 AM by niblumha | 17 Comments

Ruby on MEF: Hybrid Application

Since the last installment in this little series, I've started to consider how Ruby/C# hybrid MEF applications might look.

The result is yet another component-based calculator:

image

Besides the Radiohead arithmetic, there is one reason to get excited...

image

Ruby parts! (I bet you hadn't guessed.)

The Ruby-based export and import features are heading towards a fairly natural syntax. IOperation, for example, is a regular .NET interface type:

image 

Let's take a look at how the Ruby implementation is woven into the app.

Configuration

This is still a work-in-progress, so configuration is basic. All of the Ruby parts are loaded from a single file that is fed into the RubyCatalog:

image

The calculator_ops.rb file contains part definitions like Multiply from above.

An additional catalog adds all of the C# parts to the composition as well:

image

Main Window

The main window is a typical WPF Window that Imports a list of operations:

image

Because the MainWindow is instantiated and composed by MEF, all known exporters of IOperation will be provided, regardless of the language they're implemented in.

Bi-Directional Composition

You'll notice that the MainWindow class implements the IErrorLog contract. This allows messages from the parts to be presented to the user:

image

Parts that wish to access the IErrorLog service from Ruby can import it:

image

The integration (and IronRuby in general) treats interface contracts as Ruby Module objects, so the IErrorLog used by the Divide part could be implemented by a Ruby object, although I haven't tested that case.

Fanatics take note: I did attempt to use IronRuby's case-transforming features to allow Symbol and Apply() to be specified in their natural Ruby forms (symbol and apply()) but had no success. Hopefully I'll resolve this in a future version.

Monkeypatching the Export Type

I can't say whether this will turn out to be a good move or not, but right now it seems reasonable.

Notice this method call:

image

In order to support MEF's lazy-instantiation feature, the @error_log attribute needs to be of type System::ComponentModel::Composition::Export, which will supply the actual instance when it is required through the get_exported_object() method. Calling @error_log.get_exported_object.add_message felt decidedly unnatural, so I've added method forwarding to the Ruby version of the Export class:

image

I've had to do some type aliasing to disambiguate Export from Export<T>, but otherwise this is straightforward. Rubyists, please weigh in and let me know if this implementation is less-than-desirable :)

Source Code

Once again you can download the full source code for this article from SkyDrive.

Posted Tuesday, December 23, 2008 12:20 AM by niblumha | 0 Comments

Filed under: ,

Ruby on MEF: Imports and Exports

Well, the "Ruby Parts" implementation is slowly taking shape. If you haven't read the first article you probably should before you read on.

Exports

An export is an object that a part will hand to the outside world to fulfil a contract. Sometimes, this is the part itself. Other times, the part will expose a property or a method as an export.

MEF requires us to publish the information about what exports are available (our ComposablePartDefinition) before any object that provides the export has been created.

We can achieve this in Ruby because class definitions are executed. The export* methods can run arbitrary code and have access to the class definition that they're running within.

Without any syntactic sugar, a part definition that exports the 'answer' contract looks like:

image 

Other parts that import the 'answer' contract will get the integer value 42.

Our technique is:

  1. Keep a global table of 'part definitions' that can be updated as a Ruby script executes
  2. When a static export* method executes, create a function that can retrieve the export from a part instance (the 'export accessor')
  3. Store the export accessor along with the part's class in the table of part definitions

Each part definition ends up mapping a Ruby class to a table of contract name/function pairs.

When an export is requested from our part, the value returned is the result of executing the function that we stored for that export in the part definition.

The function can return either the object itself, an attribute, or a Proc object representing a method, which seems like a good generic foundation to build our different kinds of exports on top of.

Because self or a Proc can be returned from a property, we'll implement property exports first.

In the example, to get things started the export accessor function is explicitly specified in a block argument to the export_attr method.

The export_attr Method

This method is defined as a class method on PartDefinition.

image

So, while the MyPart class is being defined in the Ruby runtime, export_attr will create an export accessor that runs the provided block in the context of the part instance.

RubyCatalog

The meat of the add_export method creates or finds a RubyPartDefinition instance and adds an export definition to it.

image

The mysterious MefPartsCollection variable that appears in the above code is a named instance provided by the MEF RubyCatalog to the IronRuby runtime.

public class RubyCatalog : ComposablePartCatalog
{
    readonly ScriptRuntime _runtime;
    readonly ScriptEngine _ruby;
    readonly IQueryable<ComposablePartDefinition> _parts;

    public RubyCatalog(string script)
    {
        if (script == null)
            throw new ArgumentNullException("script");

        var rubySetup = new LanguageSetup(typeof(RubyContext).AssemblyQualifiedName);
        rubySetup.FileExtensions.Add("rb");
        rubySetup.Names.Add("IronRuby");

        var setup = new ScriptRuntimeSetup();
        setup.LanguageSetups.Add(rubySetup);

        _runtime = new ScriptRuntime(setup);
        _runtime.LoadAssembly(typeof(RubyPartDefinition).Assembly);
        _runtime.LoadAssembly(typeof(ExportDefinition).Assembly);
        _runtime.LoadAssembly(typeof(IEnumerable<int>).Assembly);

        _ruby = _runtime.GetEngine("IronRuby");

        var parts = new Hashtable();
        _runtime.Globals.SetVariable("MefPartsCollection", parts);
        _ruby.Execute(Script.PartDefinition);
        _ruby.Execute(script);

        _parts = parts.Values.Cast<ComposablePartDefinition>().AsQueryable();
    }

    public override IQueryable<ComposablePartDefinition> Parts
    {
        get { return _parts; }
    }
}

You can see how the "MefPartsCollection" variable is being set to a Hashtable before the script executes, and afterwards the values are retrieved as a list of ComposablePartDefinition instances.

The DLR setup in the catalog is a bit tentative. We'll refactor and extend it to be a little more user-friendly in the future.

(This catalog design assumes a single catalog per IronRuby runtime. This probably isn't going to be the best outcome for pure-Ruby applications, but for C# applications hosting Ruby parts this will work for now.)

Ruby Programming Model

The items in the MefPartsCollection are instances of the RubyPartDefinition class, indexed by Ruby part class.

RubyPartDefinition collaborates with RubyPart, RubyExportDefinition and RubyImportDefinition to create what MEF terms a 'programming model'.

I've implemented the programming model classes in C#, but they should be able to be implemented equally well in Ruby. Porting them might be an interesting exercise for the reader :)

Imports

Imports are defined using a similar technique. You can see how they work in the example code.

The Unit Tests

The solution you'll find attached to this article doesn't include an application - just a meagre selection of unit tests for the catalog.

The most interesting is this one:

[TestMethod]
public void ImportsValues()
{
    var script = @"
        class MyPart < PartDefinition
            import 'input_value' do |input|
                @input_value = input
            end

            export_attr 'output_value' do
                @input_value.get_exported_object
            end
        end
    ";

    ComposablePart part = CreateMyPart(script).CreatePart();
    Assert.AreEqual(1, part.ImportDefinitions.Count());

    var inputImport = part.ImportDefinitions.Single(
        i => ((ContractBasedImportDefinition)i).ContractName == "input_value");
    Assert.AreEqual(1, part.ExportDefinitions.Count());

    var outputExport = part.ExportDefinitions.Single();
    var testValue = "Hello, world";
    part.SetImport(inputImport, new[] { new Export(
        new ExportDefinition("input_value", null),
        () => testValue)});
    var output = part.GetExportedObject(outputExport);
    Assert.AreEqual(testValue, output);
}

Here you can see a complete roundtrip from import to export. Not groundbreaking, but I think this puts us on the right track.

Coming up...

We'll implement the basics of metadata, tidy up the syntax (I'm considering Dave's post a challenge ;)), and start to look at a hybrid application. Stay tuned!

Files

MefDlr-2008-12-13.zip

Posted Sunday, December 14, 2008 1:18 AM by niblumha | 4 Comments

Hosting Ruby Parts in MEF

MEF is fascinating because of the way some initial assumptions led to a different flavor of composition technology from the ones we've seen for .NET to date.

In my opinion, the most exciting ‘parameter variation’ in the design process for MEF was the idea that ‘parts’ should support the full range of .NET languages. The recent popularity of IronPython and IronRuby, and the inclusion of the DLR in .NET 4.0, meant that dynamic language support got first-class consideration.

As readers of my other blog may know, I’m a fan of Ruby in particular. For that reason I’m going to spend some time exploring how Ruby can fit into a MEF application.

Disclaimer:

I'm by no means a Ruby expert. Let me know if you seem me off course!

The Role of Parts

MEF’s unit of composition is the ComposablePart, or just ‘part’. Each part is self-contained and opaque to the outside world. The MEF CompositionContainer wires parts together according to the primitive Exports that each part exposes and consumes.

The independence of the part implementation behind these abstractions makes it possible to build a part just about any way you please.

The goal of the MEF/Ruby integration is to allow parts to be written in Ruby.

C# and the Attributed Part

In the default programming model, parts are defined in C# as classes, with attributes to describe their exports and imports:

image

This example is from the MEF Programming Guide, which describes these and some other interesting export and import capabilities (like method exports, which we'll look at later in this series.)

We call this the attributed programming model because MEF is agnostic about how parts are defined. A good example of an alternative programming model for an earlier version of MEF is Jason Olson's fluent version.

Translating Part Definitions into Ruby

I'm going to assume that if you are interested enough to read this far, you probably have at least a basic familiarity with the Ruby language, or the motivation to learn it.

Just as there are multiple ways of defining MEF parts in C#, there are endless ways that MEF parts could be defined in Ruby. There are two obvious ways that I can see Ruby interacting with other .NET languages via MEF:

  1. Ruby snippets fulfil a specific role in a C# application (e.g. as command macros); or,
  2. Composite applications are built using a mixture of Ruby and C#

Ruby Parts as 'Macros' (1)

The first approach would point towards supporting a minimal subset of MEF in order to supply Ruby snippets, probably as functions, to C# components:

image

For this imaginary example, a MEF integration would expose all similar functions from a script as Action<Document> delegates that could be imported by other parts. Export metadata could be used in order to describe the command as "delete selection" and this would be sufficient for including the command into user-defined toolbar buttons.

A simple technique like this is appealing for the first kind of Ruby/MEF integration, and I'm sure it is going to be implemented widely (I've already seen something similar done in Python.)

Full-Fledged Ruby Parts (2)

The second approach - building composite applications - requires that Ruby parts support most of the key MEF programming model features. It makes more sense in this case to use Ruby classes as the primary definition of a Part, and to require that the Ruby programmer has some knowledge of MEF itself.

This is the approach that I'm going to take in this series of posts.

Defining Ruby Parts

One of the wonderful things about Ruby is its flexibility. It is entirely possible to take a syntax-first approach and to work back from there towards an implementation.

My 'ideal' translation of the C# sample above would look something like:

image

It should be possible to interchange the Ruby Configuration part for the C# one in this example without changing any further code in the application. This is a really exciting possibility enabled by the DLR and MEF, and we'll try to push our implementation as far as possible in that direction.

Identifying Parts

I'm going to attempt to avoid a 'Part' base class, and instead regard any class that contains export statements as representing a part.

One thing this seems to imply is that the helper methods will be on Kernel. This might not be a good thing (it's like adding extension methods to System.Object in C#) so the base class might appear in the future.

Exports

There are three kinds of exports we need to account for: exporting the entire 'part object', exporting a property value, and exporting a method. All three of these are going to appear in the body of our Ruby class definition.

We'll need to use separate methods for each export type, so that we can differentiate between them. This is especially relevant in the case of properties/methods, which are the same under the hood in Ruby, but which need to be exported differently. A method export will be a delegate type, while a property export will be a value that is the result of invoking the property. Using export_attr and export_method would help to disambiguate this case clearly.

Imports

Imports are a bit simpler. I think that a single mechanism for importing values will suffice, and some hash parameters will allow the value to be imported into an attribute, an attribute writer (property) or perhaps via an optional block.

Where to Next?

There's no source code with this article today. I have a few unit tests working but things are a bit haphazard and not packaged up to distribute. I'm still experimenting with syntax so expect some significant changes of direction :)

I'll try to keep installments in this series short - perhaps a single unit test each. We'll work from there towards an example application that pulls everything together.

Posted Tuesday, December 09, 2008 7:29 PM by niblumha | 11 Comments

Filed under: ,

Page view tracker