LiveUI Contracts.

LiveUI provides Contracts for dependencies management. If some interface is declared as a Contract for Component then interface this implementation will be automatically resolved for Component. I.e Components work as dependency injection containers for Contracts.  This document describes how to declare and how to use Contracts.

Declaring Contracts

Technically, Contract is a marker interface describing Component-Contract relationship. There is Contract declaration example

Contract declaration sample
  1. public interface IView : IContract<VisualComponent, IView>
  2. {
  3. }

As one can see IContract interface has two generic arguments, first one is Component Contract designed for and second is type itself. Second generic argument looks redundant because it just repeats type implementing interface but for technical reasons it can not be omitted.

The same syntax is used for Contract implementation.

Contract implementation Sample
  1. public class MyView : IView, IContract<MyComponent, View>
  2. {
  3. }

Which means that View should be used as IView for MyComponent

Using Contracts

LiveUI provides following syntax for accessing Contracts:

Contract using sample
  1. var myComponent = new MyComponent();
  2. IView view = visualComponent.GetContracts().Get<IView>();

That's what happens at line 2

  • IView interface will be resolved as View 
  • new View instance would be created and accosiated with myComponent.
  • View instance would be cached in Component

There are important features of Contracts:

  • If one accesses the same contract for the same component then the same instance will be returned;
Accessing contracts sample#1
  1. var visualComponent = new MyComponent();
  2. IView view1 = visualComponent.GetContracts().Get<IView>();
  3. IView view2 = visualComponent.GetContracts().Get<IView>();
  4. Assert.AreEqual(view1, view2);
  • If one contract inherits other contract the same same instance will be returned;
Declaring inherited contracts
  1. public class CustomView : View, IContract<MyComponent, CustomView>
  2. {
  3. }


Accessing contracts sample#2
  1. View view = visualComponent.GetContracts().Get<View>();
  2. CustomView customView = visualComponent.GetContracts().Get<CustomView>();
  3. Assert.AreEqual(customView, view);


Typically contracts are used for:
  • Making components loosely coupled.
    At samples above MyComponent knows nothing about View; it knows about IView only. Thus Component and IView are loosely coupled which helps testing.

  • Associating some information with component.
    Sometimes it is needed to associate some information with component without component knowing about it. For example, when application starts some environment options can be associated with root component.

Note: To make component accessible from contract, contract type should have constructor with single argument of component type.

Registering Contracts

To make contracts work, assembly should be registered as a module using LiveUI configuration section. For example, if we implement contracts at assembly named MyFirstApplication, following should be added to configuration.

  1. <LiveUI>
  2.     <Modules>
  3.        <add moduleName="myApplication" moduleAssembly="MyFirstApplication" />
  4.   </Modules>
  5. </LiveUI>

How It Works ?

When application starts, built in ContractsModule is activated. ContractsModules iterates through all registered types and searches for IContract interface implementations. Having all IContracts it creates plan of how each contract should be instantiated. 

Internally Component uses sort of Dictionary to keep resolved contracts. When Contract is accessed, Component looks at dictionary and returns instance if it exists, else it uses ContractsModule to create new instance.