Christian Doppler Laboratory for
Automated Software Engineering

Plux.NET
MovieFinder Tutorial

Downloads

Please note that this is an alpha version of Plux. Modifications of features and programming interfaces may happen. The Plux executables are distributed "as is" and without any warranty or license. The sources are not (yet) published, and a license model for them is yet to be defined.

Table of Contents

Introduction

The sample material for this tutorial is taken from Martin Fowler's article [1] about "Inversion of Control" and the "Dependency Injection Pattern". Fowler's article uses a naive movie finder application as a running example. This tutorial shows how the movie finder application is done with Plux.NET.

Step 1: Movie application

In this example I am writing an extension that provides a list of movies directed by a particular director. The startup extension for the movie finder example is the MovieApplication class, which is an extension for the startup slot of Plux.NET. MovieApplication does not need to run in its own thread. Instead it specifies true for the ExecuteInMainThread-Parameter of the startup slot to be executed in the UI-thread.

using Plux;
[Extension("MovieApplication")]
[Plug("Startup")]
[ParamValue("ExecuteInMainThread", true)]
public class MovieApplication : IStartup {
  public void Run() {}
}

The movie application extension requires another extension that provides a list of movies directed by given director. The movie application defines a class for movie objects and a slot definition for the movie lister. A movie has two properties, a title and a director. A movie lister is expected to provide a method ListByDirector which returns a list of movies for a given director's name.

using Plux;
using System.Collections.Generic;

public class Movie {
  public string Title;
  public string Director;
  public Movie(string title, string director) {
    Title = title;
    Director = director;
  }
}

[SlotDefinition("MovieLister")]
public interface IMovieLister {
  List ListByDirector(string name);
}

Once we have the slot definition, we can use a MovieLister slot in the MovieApplication extension by adding the Slot attribute. The Plux.NET runtime sends an OnPlugged event when it creates and plugs an instance of the movie lister extension into our slot. When the extension gets plugged, movie application gets a reference to the IMovieLister interface. Movie application calls the GetByDirector method and gets a list of movies directed by "Miyazaki". It then prints each movie title to the console. Then this simple application is done and calls the Shutdown operation to exit the application.

using Plux;
using System;
using System.Collections.Generic;

[Extension("MovieApplication")]
[Plug("Startup")]
[ParamValue("ExecuteInMainThread", true)]
[Slot("MovieLister", OnPlugged="MovieLister_Plugged")]
public class MovieApplication : IStartup {
  public void Run() {}
  public void MovieLister_Plugged(object s, PlugEventArgs args) {
    IMovieLister lister = (IMovieLister) args.Extension;
    List = lister.GetByDirector("Miyazaki");
    if(movies != null) {
      foreach(Movie m in movies)
        Console.WriteLine("Title: {0}", m.Title);
    }
    Runtime.Shutdown();
  }
}

Step 2: Movie lister extension

Movie lister provides a filter by director name. As an input it needs a collection of all movies available. Another extension will provide that collection of movies. Movie lister defines another slot to aquire the movie collection.

[SlotDefinition("MovieFinder")]
public interface IMovieFinder {
  Movie[] FindAll();
}

The MovieLister extension plugs into slot MovieLister. It provides an implementation for interface IMovieLister. The ListByDirector method calls FindAll on the finder extension to get the full movie collection. ListByDirector creates a new list and returns all movies that contain the given director name. Movie lister opens a slot MovieFinder and listens to the OnPlugged event. When a movie finder gets plugged, movie lister stores a reference in field finder.

using Plux;
using System;
using System.Collections.Generic;

[Extension("MovieLister")]
[Plug("MovieLister")]
[Slot("MovieFinder", OnPlugged="MovieFinder_Plugged")]
public class MovieLister : IMovieLister {
  IMovieFinder finder = null;
  public List ListByDirector(string name) {
    Movie[] movies = finder.FindAll();
    List result = new List();
    foreach(Movie m in movies)
      if(m.Director.Contains(name))
        result.Add(m);
    return result;
  }
  public void MovieFinder_Plugged(object s, PlugEventArgs args) {
    finder = (IMovieFinder) args.Extension.
  }
}

One problem remains to addressed. MovieLister depends on a movie finder extension to provide its service. Without an extension plugged into the MovieFinder slot the movie lister is not operational. As long as movie lister is not operational it should not be plugged. Plux allows an extension to take control over when its plugged by setting the AutoPlug property of the plug to false.

Finally there is one more thing movie lister has to do. The Plux runtime automatically opens the slots of extensions when they are plugged. Since movie lister will manually plug, it also has to manually open its own slots. To open its slots manually, movie lister handles the OnCreated event and calls the OpenSlots method in class ExtensionInfo. Eventually the movie finder slot is opened. When a movie finder extension gets plugged movie lister keeps a reference in the field movie finder. Movie lister is now operational and ready to be plugged. To plug manually, movie lister calls method PlugPlugs of class ExtensionInfo.

[Extension("MovieLister", OnCreated="OnCreated")]
[Plug("MovieLister", AutoPlug=false)]
[Slot("MovieFinder", OnPlugged="MovieFinder_Plugged")]
public class MovieLister : IMovieLister {
  IMovieFinder finder = null;
  public List ListByDirector(string name) { ... }
  public void OnCreated(object s, ExtensionEventArgs args) {
    args.ExtensionInfo.OpenSlots();
  }
  public void MovieFinder_Plugged(object s, PlugEventArgs args) {
    finder = (IMovieFinder) args.Extension.
    args.SlotInfo.ExtensionInfo.PlugPlugs();
  }
}

Step 3: Movie finder extension

Movie finder provides a collection of movies. The extension BasicMovieFinder has a plug for slot MovieFinder and implements interface IMovieFinder. The FindAll method returns an array of two movies.

using System;
using Plux;
[Extension("BasicMovieFinder")]
[Plug("MovieFinder")]
public class BasicMovieFinder : IMovieFinder {
  private static Movie[] movies = new Movie[] {
    new Movie("The Godfather", "Francis Ford Coppola"),
    new Movie("Sprited Away", "Hayao Miyazaki")
  };
  public Movie[] FindAll() { return movies; }
}

Step 4: Build and run the movie finder tutorial

Open a command prompt and enter the following commands to build the movie finder tutorial:

csc /t:library /r:Plux.dll MovieApplication.cs
csc /t:library /r:Plux.dll,MovieApplication.dll MovieLister.cs
csc /t:library /r:Plux.dll,MovieLister.dll MovieFinder.cs

The C# compiler creates three plug-ins: MovieApplication.dll, MovieLister.dll and MovieFinder.dll. To run the application call the Plux runtime by entering the following command:

plux.exe /dis:MovieApplication.dll;MovieLister.dll;MovieFinder.dll

or if the plug-ins are in the same folder as plux.exe:

plux.exe

Requirements

Related Resources

Martin Fowler: Inversion of Control Containers and the Dependency Injection pattern