Concepts - 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 validators, authorizers etc., 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
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 call 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).
After using this line of code in the constructor of your class, you can use code like:
MyClass c = new MyClass();
Dim c As 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.