-
Notifications
You must be signed in to change notification settings - Fork 1
Components
This page contains information and instructions on declaring and referencing components of the Mimick framework.
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]
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]
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.
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);
The standard Dependency Injection container provided with the Mimick framework contains several features to provide automation when handling components, as listed below.
[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.
[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.
[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:
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.
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.
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