» Pattern.Service Locator
This site relies heavily on Javascript. You should enable it if you want the full experience. Learn more.

Pattern.Service Locator

acl(admin devvvv vvvvgroup)

Service provider

A key requirement in the development of vvvv45 was to write the various software components in a way that they are loosely coupled. It should be possible to use components written for 45 in the future 50 version of vvvv and the other way round, things written for 50 should be useable in 45.
In order to do that it is mandatory to introduce abstraction layers. An abstraction layer is basically a set of interfaces which describe what methods are needed or exposed by a component.
A good example for such a component is a tree viewer:
Once an input element is set to the viewer, all the viewer wants to know about this particular input element is if it has children and how to display it. The former is done by an interface called ITreeContentProvider with the method GetChildren(object) and the latter is done by an interface called ILabelProvider with methods like GetText(object) and GetImage(object).
The introduction of that abstraction made the tree viewer completely independent of the data it displays. It can work with any input element as long as there's an provider which knows how to deal with a specific element.
But what if those specific elements come from several different components? Like plugins who want to contribute to the viewer.
Here's where the service locator pattern comes into play.

Service locator pattern

A service locator is basically one central object which provides methods to register types and type mappings (RegisterType, RegisterInstance) and methods to retrieve objects of a required type (Resolve).
In our example with the tree viewer displaying elements coming from several different components, we'd set up a service locator and give each component access to it, so it has the possibility to register the services it provides (in our case type mappings from ITreeContentProvider to some content provider for element FooBar). We'd further write a content and label provider for our viewer, which simply asks the service locator for a concrete implementation of ITreeContentProvider and element FooBar and delegates the call to that conrete provider. For example the GetText method of our provider would look something like this:

string GetText(object element) {

  var labelProvider = serviceLocator.Resolve<ILabelProvider>(element);
  return labelProvider.GetText(element);

}

A more in depth explanation of the service locator pattern can be found here: http://martinfowler.com/articles/injection.html#UsingAServiceLocator

Unity

There're several different service locators available for .NET. One of them is Unity which we use in vvvv.
Note: In Unity the service locator is called a container (IUnityConatiner).

An IUnityContainer is a little more than a simple service locator. It's more like super factory, which can be extendend and configured in various ways. It allows to plug into the service creation and destruction process via extensions. That way it's possible to do some fancy stuff, like method interception (for example to do logging), lifetime management (should an object be created on every resolve call or only once per thread) and the creation of container hierachies, which are useful to override the service resolution in some circumstances.

A very good documentation on unity is available here: http://msdn.microsoft.com/en-us/library/ff663144.aspx

Event hub

The viewer needs to be updated if the data model changes. This is done through events in the ITreeContentProvider (ContentChanged) and ILabelProvider (LabelChanged). But how do the content and label providers get notified by the data model? One solution would be, that they would subscribe to model objects once they see them first, provided every model object implements the same interface, so the provider knows how to subscribe.
Problem: each provider would have to implement that logic about subscribung and unsubscribing to the objects it deals with.
Another approach is to use the container together with an event hub. Each time a model object is created, a container extension can go through the events provided by the created object and subscribe the event hub to events it knows about. After that step is done, the event hub is one central object, which can be used to retrieve all different kind of events.
The providers only need access to the event hub to get notified about underlying changes in the data model.
Access to the event hub could for example easily be given through the service locator (the unity container in our case):

var eventHub = unityContainer.Resolve<IEventHub>();

A more in depth explanation on this topic can be found here:
http://kentb.blogspot.com/2008/03/event-hub.html

anonymous user login

Shoutbox

~20d ago

manuel: very cool to generate matcap / cubemap for reflections https://cables.gl/p/pDCOCw

~20d ago

joreg: Join us for the 19th #vvvv meetup on November 11th: https://thenodeinstitute.org/event/19-worldwide-vvvv-meetup/

~29d ago

~2mth ago

joreg: @zaid please ask this in the forum: https://discourse.vvvv.org/

~2mth ago

zaid: how can i detect a changing spread in gamma? the old workflow with a change and select node isnt possible. cheers

~2mth ago

joreg: @dawoof such a question is probably better asked in the forum or chat

~2mth ago

dawoof: hey vvvvers, What are yall's fav depth-camera for body tracking? (dancing in this case) eyeing the ZED but the delivery time is long