Dependency Injection and Inversion of Control
Using the generated code produced by LLBLGen Pro is using a framework, the LLBLGen Pro framework. To fully utilize the potential of the framework, it is important that you can extend the framework by filling in the blanks left open for that purpose. For example, if you want to add validation to the framework, you should be able to do so without having to write a lot of code to make validation happen at runtime. The same goes for authorization or auditing.
To be able to do that, the LLBLGen Pro framework uses a mechanism called
Inversion of Control or in short: IoC. Inversion of control is
the simple idea of solving a dependency of class X
on class Y
, not
from within X
but from outside X
. A typical LLBLGen Pro example is an
entity validator class, derived from ValidatorBase (see for more details
Using the generated code - Validation).
Say you have a Customer entity and you've written a CustomerValidator class. You now want to instantiate a CustomerEntity instance and set its Validator property to an instance of CustomerValidator so validation of the data inside the CustomerEntity instance is performed by the CustomerValidator instance. This section describes how this Validator property is set to an instance of CustomerValidator.
What's discussed below is illustrated with the entity validator concept. The same applies to entity auditors, entity authorizers and concurrency predicate factories for entities. You can also use the mechanism for your own properties in entity classes you added yourself.#### Inversion of Control (IoC) by using Dependency Injection (DI)
Let's look at our example again: the CustomerEntity instance, let's name
that instance C
and the CustomerValidator instance, let's name that
instance V
. For the application you're writing, C
has a dependency
on V
, as C
needs the validator V
to perform validation, or better: let
the framework perform all kinds of validations at runtime by calling
into V
. It might be C
doesn't need V
in particular; it can also use
another validator for a customer entity class, one which has slightly
different rules: the SpecialCustomerValidator. Let's call the instance
of that class in our example SV
.
Because LLBLGen Pro uses inversion of control (IoC) for e.g. validators,
authorizers, you're able to select which validator you want to use
for C
, namely V
or SV
, without changing the code for C
, as the
dependency of C
on its validator to use isn't defined inside C
, but
outside C
. With outside C
is meant: any outside source can set the
validator of C.
This gives you the freedom to use a separate mechanism
to set the validator for C
, by injecting the validator at runtime when
C
is instantiated. This injecting is called Dependency Injection
(DI), as it injects an object Y
into an object X
where X
depends
on, which means it is simply setting a property on X to the value Y
.
That all might sound complicated but it's actually very simple: Given
our example with the CustomerEntity instance C
and the two validator
objects V
and SV
, we can use a Dependency Injection (DI) mechanism to
inject either V
or SV
into C
at runtime, which comes down to set the
property C.Validator
to either V
or SV
. For .NET there are several DI
frameworks available to perform this injection at runtime for you:
StructureMap, ObjectBuilder, Spring.NET or the Castle Project to name a
few.
One of the things these frameworks all have in common is that they use a factory which builds the entity. So instead of using a normal object instantiation statement with the new keyword, you'll call a factory and it will return the object you requested, injecting all objects to inject for you. It can be inconvenient not to be able to use the new keyword and always have to call a factory, as not using the factory will bypass the injection mechanism and not set the objects you want. Also you'll need to use another framework to do the dependency injection for you.
To help you get up and running without learning another framework, LLBLGen Pro supports its own Dependency Injection mechanism. If you're comfortable with the 3rd party frameworks for dependency injection, you're free to use these, as the LLBLGen Pro framework doesn't rely on its own DI mechanism to function properly: you can inject validators, authorizers etc. into entities with these other frameworks just fine and the injected objects will function normally. The LLBLGen Pro DI mechanism is discussed in the next paragraph.
LLBLGen Pro's ways to inject dependent objects into entities
LLBLGen Pro supports a couple of different ways to inject objects entities depent on into entity objects at runtime.
- Overriding a Create method to create instances at runtime. This mechanism allows developers to write code to insert objects at runtime into entities. For example, one could override in a partial class the entity class method CreateValidator to create a validator object when the entity class is instantiated. One could also use the override of this method to call into a factory to produce the validator for the particular context. See the LLBLGen Pro runtime framework reference manual for details about EntityBase and EntityBase2 and which methods are available to you in these classes (Which are the base classes for entities in resp. SelfServicing and Adapter) and what their purposes are.
- Using the Dependency Injection mechanism build into LLBLGen Pro. This mechanism offers developers a way to write validator classes, authorizer classes, ConcurrencyPredicateFactory classes etc. in a separate project without any ties to the generated code. At runtime instances of these classes are injected into entity class instances, without the necessity of overriding methods in partial classes of the entity classes. When an entity class is instantiated, be it through a factory or with the new keyword, the LLBLGen Pro framework will automatically find the instances to inject and will perform the injection for you.
The DI mechanism in LLBLGen Pro is used for injecting objects into entity class instances: entity classes are prepared to get the objects they depend on injected by the DI mechanism, other classes are not. This doesn't mean you can't enable these classes to use the DI mechanism: it's easy to enable other classes to be used in the DI mechanism.
All you have to do is tell the DependencyInjectionProvider to inject the objects the instance relies on, from the constructor of the class. Do this with the following code: (For entities, you don't have to do anything, it's been taken care of for you. Only use the following code if you want to use the LLBLGen Pro DI mechanism to inject objects into classes not yet prepared for DI).
DependencyInjectionInfoProviderSingleton.PerformDependencyInjection(this);
After using this line of code in the constructor of your class, you can use code like:
MyClass c = new MyClass();
and c
will get all objects to inject into an instance of MyClass
injected. For entity classes, you don't have to do anything, it's been
taken care of for you.
To setup and use the LLBLGen Pro Dependency Injection mechanism and for example how to use Dependency Injection Scopes, please see the section Setting up and using Dependency Injection in the Using the Generated Code section to get started.