Skip to content

Components

Chris Copeland edited this page Dec 14, 2018 · 2 revisions

Summary

This page contains information and instructions on declaring and referencing components of the Mimick framework.

Dependency Injection

The Mimick framework comes with a standard Dependency Injection container, with support for concrete and abstract component registration. The registration of components can be done manually through the framework IComponentContext, automatically using the Component attribute decoration, or by explicitly constructing components through a class decoration with the Configuration attribute.

Component Attribute

[Component]
public class CustomService
{

}

The Component attribute indicates that the associated class should be registered as a component of the framework. If the containing assembly is registered to the IComponentContext, all classes with this attribute will be discovered.

Configuration Attribute

[Configuration]
public class CustomConfiguration
{
    [Component]
    public CustomService GetCustomService() => new CustomService();
}

The Configuration attribute can be used in conjunction with the Component attribute to indicate that a class exposes configurations or components, and that any methods or properties decorated with Component should be registered as an explicit instance component.

Manual

IComponentContext components = FrameworkContext.Current.ComponentContext;

components.Register<CustomService>();
components.Register<ICustomService, CustomService>();
components.Register<ICustomService>(new CustomService());
components.Register(typeof(CustomService));
components.Register(typeof(ICustomService), typeof(CustomService));
components.Register(new CustomService());

The components can be added manually using the Register method of the IComponentContext instance. Components can be registered as interface implementations, or just as concrete classes. The Register method also produces a configuration instance which can be used to control the scope of the component.

components.Register<CustomService>().ToScope(Scope.Adhoc);

Features

The standard Dependency Injection container provided with the Mimick framework contains several features to provide automation when handling components, as listed below.

Interface Implementations

[Component]
public class CustomService : ICustomService
{

}
var customService = FrameworkContext.Current.ComponentContext.Resolve<ICustomService>();

When a component has been registered, with or without an explicit interface declaration, the framework will implicitly find interfaces which have been implemented. This means that a concrete service class which provides the body for a corresponding interface will have the interface type automatically registered. The framework excludes any interfaces included as part of the standard .NET Framework or netstandard libraries.

Naming

[Component("MyService")]
public class MyCustomService : ICustomService
{
}

[Component("YourService")]
public class YourCustomService : ICustomService
{

}
var myCustomService = FrameworkContext.Current.ComponentContext.Resolve<ICustomService>("MyService");
var yourCustomService = FrameworkContext.Current.ComponentContext.Resolve<ICustomService>("YourService");

A component can also be provided a name which identifies the component uniquely within the application. This allows for multiple implementations of an interface by a concrete class which can be resolved based on the name.

Scoping

[Component(Scope.Adhoc)]
public class CustomService
{
}

A component can be scoped, which determines how the component is stored and persisted within the framework. There are currently 3 different scope states which are supported:

Adhoc

The component is created when necessary, never persisted within the container. When resolved using the IComponentContext.Resolve() method, or when accessed for the first time through a member decorated with Autowired, the component will be constructed. An auto-wired field or property will only construct the component once, when the field or property is first accessed. An auto-wired parameter will always have a new component instance constructed.

Singleton

The component is persisted as a lazy singleton instance within the container, and is created when the component is first accessed through either the IComponentContext.Resolve() method, or through a member decorated with the Autowired attribute.

Thread

The component is created as a lazy singleton instance against the current thread, persisting similar to the Singleton scope, except that the component is attached to the current thread, and will persist for the duration that the thread remains alive.

Components under the Thread scope will not be disposed correctly, but will be garbage collected