TypeFactory
The TypeFactory is responsible for actually creating types inside Catel. It uses the following mechanism:
- List all the constructors, order them from most parameters to least parameters
- While (constructors available) try to construct type using injection
- If all constructors fail, the
TypeFactory
will fallback toActivator.CreateInstance()
Dependency injection
The ServiceLocator in Catel supports dependency injection.
Introduction to dependency injection
Some people make dependency injection hard to understand, or maybe they don’t understand it themselves. Dependency injection simply means that instead of hard referencing or instantiating other classes (dependendies), the dependencies are injected into the class via the constructor.
Example 1: bad, instantiates the dependencies itself
public class MyClass
{
private IFirstDependency _firstDependency;
private ISecondDependency _secondDependency;
public MyClass()
{
_firstDependency = new FirstDependency();
_secondDependency = new SecondDependency();
}
}
Example 2: good, retrieves the dependencies via the service locator)
public class MyClass
{
private IFirstDependency _firstDependency;
private ISecondDependency _secondDependency;
public MyClass()
{
_firstDependency = ServiceLocator.Instance.ResolveType<IFirstDependency>();
_secondDependency = ServiceLocator.Instance.ResolveType<ISecondDependency>();
}
}
Example 3: good, gets the dependencies injected
public class MyClass
{
private IFirstDependency _firstDependency;
private ISecondDependency _secondDependency;
public MyClass(IFirstDependency firstDependency, ISecondDependency secondDepdenceny)
{
Argument.IsNotNull("firstDependency", firstDependency);
Argument.IsNotNull("secondDependency", secondDependency);
_firstDependency = firstDependency;
_secondDependency = secondDependency;
}
}
There are other ways of using dependency injection, for example via attributes. This documentation will focus on dependency injection via the constructor only
Using dependency injection in Catel
Dependency injection via the ServiceLocator in Catel is enabled by default. This means that when a type is resolved from the container, it will automatically use dependency injection to construct the type if it is not registered as instance.
It will first search for all available constructors on the type that will be instantiated. Then, for each constructor, starting with the one with the most parameters, it will try to retrieve all values. If one fails, it will go to the next. If all fail, it will try to use the default constructor without parameters. If that fails as well, then the type cannot be constructed and an exception will be thrown.
To get a better understanding of what happens, see the class below:
public class MyClass
{
private IFirstDependency _firstDependency;
private ISecondDependency _secondDependency;
public MyClass()
: this(null) { }
public MyClass(IFirstDependency firstDependency)
: this(firstDependency, null) { }
public MyClass(IFirstDependency firstDependency, ISecondDependency secondDepdenceny)
{
_firstDependency = firstDependency;
_secondDependency = secondDependency;
}
}
When the MyClass will be retrieved from the ServiceLocator, this will happen:
- Find constructor with most parameters (the one with both firstDependency and secondDependency). If both IFirstDependency and ISecondDependency can be resolved from the ServiceLocator, the type will be constructed with the constructor. Otherwise it will proceed with step 2.
- Find next constructor with most parameters (the one with only firstDependency). If IFirstDependency can be resolved from the ServiceLocator, the type will be constructed with the constructor. Otherwise it will proceed with step 3.
- At this point, no constructor could be used. In this case, the ServiceLocator will try to use the default constructor (the one without parameters) as last resort to instantiate the type.
Disabling dependency injection
Maybe you don’t want dependency injection because it does not give you what you need or you want a very, very small improvement in performance. In that case, the dependency injection can be disabled using the code below:
ServiceLocator.Default.SupportedDependencyInjection = false
Custom initialization
All types created with the TypeFactory
can be initialized with custom code. This can be done by implementing the INeedCustomInitialization
interface. As soon as a type is created, the TypeFactory will check whether it implements the INeedCustomInitialization interface. If so, it will call the Initialize method of the interface.
To prevent misuse of the Initialize
method, it is best to implement the interface explicitly
Contributions
We would like to thank the following contributors:
Want to contribute to the documentation? We have a guide for that!
Questions
Have a question about Catel? Use StackOverflow with the Catel tag!