In .NET 6 appeared new feature is DI by type anonymous delegate:
Questing:
I have many clases inherited from based class with constructor.
now I have to write such long initializations
Isn't there a way to get rid of this writing?, for example, like this (psevdocode)
This is how parameter binding in minimal APIs (introduced in .NET 6) works and this is handled by the framework (ASP.NET Core). But it is not completely new idea and it is not bound to the anonymous labmdas - injection in controllers actions via FromServicesAttribute is present from the first ASP.NET Core (see the applies to section) version.
As for tackling the parameter injection into the base class issue - one way around would be just creating class holding those parameters, register it in DI and injecting it. Something like this:
public class BaseClassParameters
{
public BaseClassParameters (A a, B b, ...) {A = a; ...}
public A A { get; }
...
}
public class BaseClass
{
public BaseClass(BaseClassParameters p) { // copy from p}
}
public class ChildClass : BaseClass
{
public ChildClass(BaseClassParameters p): base(p) // can create ChildClassParameters : BaseClassParameters if needed or just add deps on this level
{
}
}
services.AddTransient<BaseClassParameters>(); // or use needed lifetime for class hierarchy here
Related
I'm currently facing an issue for which I have found some partial solutions, but not the one that actually makes me believe I cannot do better.
So, to put in simple, I'm using the Dependency Injection, and I'm facing a circular reference error. Here's something similar to the code I am using.
First, I have a IMyBuilder interface:
public interface IMyBuilder { }
Then, I have an abstract class that implements the interface, and a bunch of class extending the abstract one:
public abstract class MyBuilderBase<DTO> : IMyBuilder
{
public abstract Dto GetDto();
}
public class UserBuilderDto : MyBuilderDto<UserDTO> { ... }
public class ProfessorBuilderDto : MyBuilderDto<ProfessorDTO> { ... }
public class AnimalBuilderDto : MyBuilderDto<AnimalDTO> { ... }
Then, I have a ProviderService, which helps me get the right IMyBuilder based on the DTO type. This ProviderServicedepends on ALL the IMyBuilder, like so:
public class ProviderService
{
private readonly IEnumerable<IMyBuilder> _builders;
public ProviderService(IEnumerable<IMyBuilder> builders)
{
_builders = builder;
}
public IMyBuilder GetBuilder<DTO>()
{
return _builders.OfType<MyBuilderBase<DTO>>().FirstOrDefault();
}
}
Finally, last piece of my code is the registration of the services, like so:
services.AddScoped<IMyBuilder, UserBuilderDto>();
services.AddScoped<IMyBuilder, ProfessorBuilderDto>();
services.AddScoped<IMyBuilder, AnimalBuilderDto>();
services.AddScoped<ProviderService>();
Notice that I register my builder as IMyBuilder: this way I can use the parameter IEnumerable<IMyBuilder> in the constructor of ProviderService.
Ok, now that we have all the inputs, here's the problem: inside the abstract method MyBuilderBase.GetDto I might need some other builder! Therefore, MyBuilderBase needs ProviderService, something like this:
public class AnimalBuilderDto : MyBuilderDto<AnimalDTO>
{
private readonly ProviderService _providerService;
public AnimalBuilderDto(ProviderService providerService)
=> (_providerService) = (providerService)
public AnimalDto GetDto()
{
// using _providerService
}
}
At this point you can clearly see where is my problem:
ProviderService requires AnimalBuilderDto
AnimalBuilderDto requires ProviderService
ProviderService requires AnimalBuilderDto
...
Circular dependency, thus my application crashes.
So, I've investigated this for a while, and I've come up with these solutions.
LAZY INITIALIZATION IN PROVIDER SERVICE
This would be something like here: https://thomaslevesque.com/2020/03/18/lazily-resolving-services-to-fix-circular-dependencies-in-net-core/
Basically, in the constructor of ProviderService I would not directly need to initialize the single IBuilderDto, avoiding the circular dependency..
What I don't like is that it seems a workaround, and not a solution. Also, if by any chance I put a breakpoint into providerService constructor, and inspect the lazy property, the application crashes.. Yeah, workaround.
METHOD INJECTION
I would need to change the signature of the abstract method as follow:
public abstract Dto GetDto(ProviderService providerService);
This way, I would not need the AnimalBuilderDto to depends on ProviderService, REMOVING the circular dependency.
This solution seems a real solution (it removes the circular dependency), but it adds a cost, which is the need of bringing this instance of ProviderService along all the application in order to use it when calling GetDto.
Here's end my investigation. Though, both solution does not seems to fix my problem! Ok, the second one does actually fix the problem, but create another one, which is the need of bringing the instance across all method calls.
Question is: is there any better solution to make a provider class like my ProviderService being reusable inside the same classes that it exploses?
Here's a quick and dirty way to break the circular reference, using an open generic service locator factory.
public interface IMyBuilder<TDTO>
{
TDTO GetDto();
}
public class BuilderFactory<TDTO>
{
private readonly IServiceProvider services;
public BuilderFactory(IServiceProvider services)
{
this.services = services;
}
public IMyBuilder<TDTO> GetBuilder() => services.GetRequiredService<IMyBuilder<TDTO>>();
}
public abstract class MyBuilderBase<DTO> : IMyBuilder<DTO>
{
public abstract DTO GetDto();
}
public class UserDTO { }
public class UserBuilderDto : MyBuilderBase<UserDTO>
{
private BuilderFactory<AnimalDTO> animalFactory;
public UserBuilderDto(BuilderFactory<AnimalDTO> animalFactory)
{
this.animalFactory = animalFactory;
}
public override UserDTO GetDto()
{
var animalBuilder = animalFactory.GetBuilder();
throw new NotImplementedException();
}
}
public class AnimalDTO { }
public class AnimalBuilderDto : MyBuilderBase<AnimalDTO>
{
private BuilderFactory<UserDTO> userFactory;
public AnimalBuilderDto(BuilderFactory<UserDTO> userFactory)
{
this.userFactory = userFactory;
}
public override AnimalDTO GetDto()
{
var userBuilder = userFactory.GetBuilder();
throw new NotImplementedException();
}
}
services.AddScoped(typeof(BuilderFactory<>));
services.AddScoped<IMyBuilder<AnimalDTO>, AnimalBuilderDto>();
services.AddScoped<IMyBuilder<UserDTO>, UserBuilderDto>();
Create an event in consumer class and fire it , once fired make the server class return its current instance
If the Builders use functions from ProviderService that use the Builders too, creating a factory is a way to break the cycle (at least in terms of timing, because the instances of the Builders are created at a later point in time and not upon registration.
However, if the Builders use only functions from ProviderService that do not rely on the Builders themselves, one other option is to move the functionality that is used in GetDto into another class that can be injected into both the Builders and the ProviderService. This way, the circular dependency is removed and both classes still have access to the functionality.
Basically, from
ProviderService -> Builders -> ProviderService
to
ProviderService -> Builders -> SharedFunctions
-> SharedFunctions
Whether or not the Builders and the ProviderService use the same instance of SharedFunctions then depends on the scope that you register it in the IoC container.
I'm having trouble with getting generics and DI to work together in an MVC Core project. I have a generic class (this is just a fragment). I need to initialize Input and Output because of how these are used in other parts of the code, so I'm using Activator to provide initial values and the new() constraint.
public class Message<TIn, TOut> :
where TIn : class, IMessagePart, new()
where TOut : class, IMessagePart, new() {
public Message(){}
public Message(TIn inpart, TOut outpart) {
Input = inpart;
Output = outpart;
}
public TIn Input { get; set; } = (TIn)Activator.CreateInstance(typeof(TIn));
public TOut Output { get; set; } = (TOut)Activator.CreateInstance(typeof(TOut));
}
I have other classes that are used by this, and they have some static utility classes. I'm trying to replace these static classes using DI.
public class Project : IMessagePart{
int y = 1;
var x = StaticUtilityClass.StaticMethod(y);
}
is used like this
var projectMessage = new Message<Project, Project>();
I'm converting the static utility classes to instance classes and injecting them. I'm using the built-in .Net core container. I converted the utilities to instance classes and registered them as concrete singletons in the container. For most things I can just do the normal-
public class SomeClass{
private readonly UtilityClass _utility;
public SomeClass(UtilityClass utility){
_utility = utility;
var x = _utility.Method(1);
}
Things work fine until I get to the generics. I can't do constructor injection on projectMessage, because the generic needs to new it up and it has the new() constraint, so I need a parameterless constructor. If I add just the an injecting constructor I get
'Project' must be a non-abstract type with a public parameterless
constructor in order to use it as parameter 'TIn' in the generic type
or method 'Message'.
and if I add both constructors Activator is only going to call the one without parameters, so DI isn't invoked. I tried using the overload of CreateInstance a few different ways, but no luck tricking it.
Any suggestions here? I don't know if I should stay with statics, try some sort of service locator approach, or if there is a different way to writing the generic.
The answer to why you are getting the error you're seeing is the new() constraints. That specifies that the parameter must have a public parameterless constructor. Which is exactly what your error says. Removing that constraint should fix that error. However, you still have another issue if you want to use DI.
Aside from IMessagePart none of your classes have backing interfaces. In order to use DI effectively you need to define an IMessage, IProject etc. Then your container can create specific instances at runtime, rather than using the Activators like you are now. So your Message declaration would look like:
public class Message<TIn, TOut> : IMessage,
where TIn : class, IMessagePart
where TOut : class, IMessagePart
{
public TIn input { get; set; }
public TOut output { get; set; }
public Message(TIn inpart, TOut outpart) {
this.input = inpart;
this.output = outpart;
}
}
You would setup your DI container something like:
public Startup()
{
var container = new DiContainer(); // I know this is the wrong name; I'm not familiar with the built in container naming and functionality.
container.Register<IMessage>();
container.Register<IMessagePart>();
container.Register<IProject>();
// Register other stuff here
}
Change the syntax there for your specific container. You also have the option of registering your instances something like:
container.Register<Message>(() => Message(part1, part2));
so that you specifically inject a Message that is newed up at Startup time, but that's not really ideal in most cases. Usually you want your DI container to dynamically create an instance as needed (hence the interfaces), rather than using a single concrete instantiation. There are exceptions of course; a SQL connection is one common one.
I got trouble when design class for my project. Currently, we developed 2 projects with the same structure but have some differences inside.
At project A, I have class ACore that includes class AConfiguration, AEquipmentManager. And I made an instance for object ACore that at everywhere in project, i can use: Acore.AConfiguration.XYZ (XYZ is method or property of AConfiguration class) or ACore.AEquipmentmanager.ABC(ABC is method or property of AEquipmentManager class)
At project B, I still have same structure with project A (BCore, BConfiguration, BEquipmentManager). But BConfiguration has different with AConfiguration (because each project has different configuration) and BEquipmentManager also has different with AEquipmentManager.
I want to reuse code for class ACore and BCore because they have the same code (Initialize EquipmentManager, Initialize Configuration, Dispose EquipmentManager, Dispose Configuration,...). Now, I want to write a library BaseCore that have the same structure with ACore and BCore (there are 2 class Configuration, EquipmentManager, same Intialize function, Dispose function), and with specific project (like A project, B project, or even C, D project later) i can use BaseCore library class (for reuse code) and just implement XEquipmentManager, XCofiguration depend on each project.
What is the best way I should design in this case? Thank for sharing your idea.
Regards,
Hoa Nguyen
I think you're on the right track,
But I would do it with interfaces:
Implement Core class that uses class that implements IConfigurable.
Make sure AConfiguration implements IConfigurable and all the
relevant methods.
Alternativly you can do something like that:
Implement Core class that uses Configuration class.
Implement AConfiguration/BConfiguration that inherits from
Configuration.
Reference A and B to the same Core class and that's it.
Hope it helps.
Does AConfiguration and BConfiguration have the same set of methods with different implementations or do the set methods also differ? If the set of methods are the same you could do it with interfaces. You could define an interface for configuration and equipmentamanager. Then you just BaseCore using these interface. Then you can supply the specific implementation in the construction of BaseCore Something like this (leaving out the singleton stuff)
interface IConfiguration
{
void somefunc();
}
interface IEquipmentManager
{
void someOtherFunc();
}
class BaseCore
{
private IConfiguration conf;
private IEquipmentmanager eq;
private BaseCore(){};
public BaseCore(IConfiguration inConf, IEquipmentmanager inEq) :
conf(inConf), eq(inEq)
{
conf.someFunc();
}
}
class AConfiguration : IConfiguration
{
public void someFunc()
{
do stuff!
}
public int intprop{get;set;}
}
class AEquipmentmanager : IEquipmentmanager
{
public void someOtherFunc()
{
do stuff!
}
}
Note you have to initialize an instance of AConfiguration and AEquipmentmanager. Before the construction of BaseCore like so
AConfiguration conf = new AConfiguration();
AEquipmentmanager eq = new AEquipmentmanager();
BaseCore base = new BaseCore(conf eq);
Alternatively you can simply create a BaseCore constructor that takes some enum to signify which implementation to you and then initialize an instance of the appropriate class in the BaseCore Constructor.
Alternatively you could possibly to it by implementing BaseCore with to Generic parameters and provide the the configuration and equipmentmanager implementation through these. You could still use the interfaces just the same but implement BaseCore with limits on the Generic arguments. BaseCore would look something like this:
class BaseCore<Configuration_type,Equipmentmanager_type>
where Configuration_type : IConfiguration, new()
where Equipmentmanager_type : IEquipmentmanager, new()
{
public Configuration_type Configuration {get;};
public Equipmentmanager_type Equipmentmanager {get;};
BaseCore()
{
Configuration = new Configuration_type();
Equipmentmanager = new Equipmentmanager_type();
}
}
This however puts the constraint on the types that they need a parameterless constructor. Initialization could supposedly be done afterwards though.
If you want to specialize your core for a specific configuration you can inherit from it like this
class Acore<Configuration_type,Equipmentmanager_type> :
BaseCore<Configuration_type,Equipmentmanager_type>
where Configuration_type : AConfiguration ,new()
where Equipmentmanager_type : AEquipmentmanager, new()
{
Acore() : base()
{
Configuration.intprop = 10;
}
}
Note that i added a property on AConfiguration that is not accessible in BaseCore but is in ACore
I am getting confused with the scenario of 2 classes implementing the same interface and Dependency Injection.
public interface ISomething
{
void DoSomething();
}
public class SomethingA : ISomething
{
public void DoSomething()
{
}
}
public class SomethingAB : ISomething
{
public void DoSomething()
{
}
}
public class Different
{
private ISomething ThisSomething;
public Different(ISomething Something)
{
ThisSomething = Something;
}
}
I have seen online examples say that this is valid but you would only use one class at a time. So if the app is running at SiteA you tell your IOC to use SomethingA but if its at SiteB you tell it to use SomethingAB.
Is it considered bad practice therefore to have one app that has 2 classes that implement 1 interface and for it to try to use both classes? If its not how do you tell the IOC which class to use in the relevant circumstance?
UPDATE: To explain it better I will use Ninject's example:
public class Samurai
{
private IWeapon Weapon;
public Samurai(IWeapon weapon)
{
this.Weapon = weapon;
}
}
public class Sword : IWeapon
{
...
}
public class Gun : IWeapon
{
...
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
this.Bind<IWeapon>().To<Sword>();
this.Bind<IWeapon>().To<Gun>(); //Just an example
}
}
So now you have 2 classes that use IWeapon. Depending on something or a context in your app you want Samurai to have a Sword sometimes or a Gun at other points. How do you make this happen? How do you handle that "if" scenario??
I don't think that this is a bad practice in the general case. There are situations where you could need different implementations of the same interface inside the same application and based on the context use one or another implementation
As far as how to configure your DI to enable this scenario, well, it will depend on your DI of course :-) Some might not support it, others might not, others might partially support it, etc..
For example with Ninject, you could have the following classes:
public interface ISomething
{
}
public class SomethingA : ISomething
{
}
public class SomethingB : ISomething
{
}
public class Foo
{
public Foo(ISomething something)
{
Console.WriteLine(something);
}
}
public class Bar
{
public Bar(ISomething something)
{
Console.WriteLine(something);
}
}
and then use named bindings when configuring the kernel:
// We create the kernel that will be used to provide instances when required
var kernel = new StandardKernel();
// Declare 2 named implementations of the same interface
kernel.Bind<ISomething>().To<SomethingA>().Named("somethingA");
kernel.Bind<ISomething>().To<SomethingB>().Named("somethingB");
// inject SomethingA into Foo's constructor
kernel.Bind<Foo>().ToSelf().WithConstructorArgument(
"something", ctx => ctx.Kernel.Get<ISomething>("somethingA")
);
// inject SomethingB into Bar's constructor
kernel.Bind<Bar>().ToSelf().WithConstructorArgument(
"something", ctx => ctx.Kernel.Get<ISomething>("somethingB")
);
Now when you request an instance of Foo it will inject SomethingA into it its constructor and when you request an instance of Bar it will inject SomethingB into it:
var foo = kernel.Get<Foo>();
var bar = kernel.Get<Bar>();
i worked with Unity and spring in this context and i think that interest lies in having a weak coupling between packages, ie classes, the ability to change service or point of entry is a consequence of the ioc.
ioc provides flexibility in the use of service, or from the time the services implement the same interface,
If Utilize Service A Service B and Service is in the service package A and package B is in B.
Package A has no reference on the package b, but the service A has a reference on the package containing the interfaces.
Therefore we conclude that we have a weak coupling between package A and package b.
Having multiple implementations mapped to the same interface isn't really bad practice, but it isn't he most common usage pattern.
You didn't specify a specific DI tool, but if you use Unity, you can do this with named instances. See here: Unity - how to use multiple mappings for the same type and inject into an object
I'm trying to get my head around DI/IoC, NHibernate and getting them to work nicely together for an application that i'm developing. I'm quite new to both NHibernate and DI/IoC so not quite sure whether what i'm doing is the sensible way to be going about it. This is the scenario:
The application provides users with the ability to calculate a particular value (known as the margin) for a particular financial transaction. The calculation of the marging value for each transaction is carried out by concrete implementations of an abstract MarginCalculator class and the concrete implementation to be used depends on the type of the product for the particular transaction (given by a certain field of the product object). The concrete calculator class is accessed via a property on the product class. i.e.
public class Transaction
{
private double _margin;
private Product _product;
private Client _client;
public double Margin { get; }
public Product Product { get; }
public Client Client { get; }
public Transaction(Product p, Client c)
{
_product = p;
_client = c;
}
public void CalculateMargin()
{
_margin = _product.MarginCalculator.CalculateMargin();
}
}
public class Product
{
private string _id;
private string _productType;
... Other fields
public string Id { get; }
public string ProductType { get; }
public MarginCalculator MarginCalculator
{
get { return MarginCalculatorAssembler.Instance.CreateMarginCalculatorFor(this.ProductType); }
}
}
public class MarginCalculatorAssembler
{
public static readonly MarginCalculatorAssembler Instance = new MarginCalculatorAssembler();
private MarginCalculatorAssembler ()
{
}
public MarginCalculator CreateMarginCalculatorFor(string productType)
{
switch (productType)
{
case "A":
return new ConcreteMarginCalculatorA();
case "B":
return new ConcreteMarginCalculatorB();
default:
throw new ArgumentException();
}
}
}
public abstract class MarginCalculator
{
public abstract double CalculateMargin();
}
public class ConcreteMarginCalculatorA : MarginCalculator
{
public override double CalculateMargin
{
// Perform actual calculation
}
}
public class ConcreteMarginCalculatorB : MarginCalculator
{
public override double CalculateMargin
{
// Perform actual calculation
}
}
Users select a particular client and Product from dropdowns and the corresponding clientId and productId are passed to repositories that then use NHibernate to populate product and client objects before they're injected into the transaction object. In my current setup the Transaction receives its Product and Client dependencies via constructor dependency injection (no IoC container used as yet) i.e.
public class ProductRepository : IRepository<Product>
{
public Product GetById(string id)
{
using (ISession session = NHibernateHelper.OpenSession())
return session.Get<Product>(id);
}
}
/* Similar repository for Clients */
IRepository<Client> clientRepository = new ClientRepository();
IRepository<Product> productRepository = new ProductRepository();
Client c = clientRepository.GetById(clientId);
Product p = productRepository.GetById(productId);
Transaction t = new Transaction(p, c);
The following are what i'm hoping to get ideas on:
A. Is it considered OK to be accessing the MarginCalculator (which is essentially a service) through the Product domain object or should, as suggested here, (http://stackoverflow.com/questions/340461/dependency-injection-with-nhibernate-objects) the code be restructured so as to remove service dependencies from the domain objects and instead create a new TransactionProcessor class that takes the abstract MarginCalculator as a dependency (along the lines of what's described here (http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/03/31/ptom-the-dependency-inversion-principle.aspx) i.e.
public class TransactionProcessor
{
private readonly MarginCalculator _marginCalculator;
public TransactionProcessor(MarginCalculator marginCalculator)
{
_marginCalculator = marginCalculator;
}
public double CalculateMargin(Transaction t)
{
return _marginCalculator.CalculateMargin(Transaction t);
}
}
public abstract class MarginCalculator
{
public abstract double CalculateMargin(Transaction t);
}
B. Is it possible to use an IoC Container to get a Transaction object with NHibernate populated/generated Product and Client dependencies injected? i.e. Given a productId and clientId, both provided by the user, is it possible to have something like:
// pseudocode
Transaction t = IoC.Resolve<Transaction>(productId, clientId);
such that the container resolves the Product and Client dependencies of the Transaction object, NHibernate is utilised to populate the Product and Client based on the productId and clientId and then the populated Product and Client are injected into the Transaction?
C. In a typical DI scenario, if class A has a dependency on interface B then the following might be done:
IInterfaceB b = new ClassB();
A a = new A(b);
interface IInterfaceB
{
}
class B : IInterfaceB
{
}
public class A
{
private IIntefaceB _b;
public A(IInterfaceB b)
{
_b = b;
}
}
However, this, which is virtually how all examples of DI are shown, assumes that the implementor of IInterfaceB (in this case Class B) is known at design time. Is there a way to use DI in such a way that the implementor is determined at runtime?
Many thanks
Matthew
A) If you're going to access the MarginCalculator through the Product domain object, you might as well cut out the middle man and let the DI/IOC container inject the MarginCalculator for you. You can even get rid of the MarginCalculatorAssembler because most DI/IOC containers do most of the boilerplate code of object construction for you.
B and C) It's very possible. In fact, here's how your code would look like if you used LinFu:
// No need to change the Transaction class
public class Transaction
{
private double _margin;
private Product _product;
private Client _client;
public double Margin { get; }
public Product Product { get; }
public Client Client { get; }
public Transaction(Product p, Client c)
{
_product = p;
_client = c;
}
public void CalculateMargin()
{
_margin = _product.MarginCalculator.CalculateMargin();
}
}
It would be nice if you could get a DI/IOC to inject the product and client instances into the constructor--but before we do that, you need to register the dependencies with the container. Here's how you do it with LinFu.IOC:
// Next, you'd have to tell LinFu to automatically register your product class:
[Factory(typeof(Product))]
public class ProductFactory : IFactory
{
object CreateInstance(IServiceRequest request)
{
// Grab a copy of the IRepository from the container
var repository = container.GetService>();
// Get the id (this assumes that your id is an Int32)
var id = (int)request.Arguments[0];
// Return the product itself
return repository.GetById(id);
}
}
// Do the same thing with the Client class
// (Note: I did a simple cut and paste to keep things simple--please forgive the duplication)
[Factory(typeof(Client))]
public class ClientFactory : IFactory
{
object CreateInstance(IServiceRequest request)
{
// Grab a copy of the IRepository from the container
var repository = container.GetService>();
// Get the id (this assumes that your id is an Int32)
var id = (int)request.Arguments[0];
// Return the client itself
return repository.GetById(id);
}
}
[Factory(typeof(Transaction))]
public class TransactionFactory : IFactory
{
object CreateInstance(IServiceRequest request)
{
// Note: Argument checking has been removed for brevity
var container = request.Container;
var arguments = request.Arguments;
var productId = (int)arguments[0];
var clientId = (int)arguments[1];
// Get the product and the client
var product = container.GetService(productId);
var client = container.GetService(clientId);
// Create the transaction itself
return new Transaction(product, client);
}
}
// Make this implementation a singleton
[Implements(typeof(MarginCalculator), LifecycleType.Singleton)]
public class ConcreteMarginCalculatorA : MarginCalculator
{
public override double CalculateMargin()
{
// Perform actual calculation
}
}
Once you have all that code compiled in one of your assemblies, here's all you need to do to load it into the container:
var container = new ServiceContainer();
container.LoadFrom(AppDomain.CurrentDomain.BaseDIrectory, "YourAssembly.dll");
...Now for the fun part. In order to create your transaction object with the given product and client ID, here's the call you need to make to LinFu.IOC's container:
int productId = 12345;
int clientId = 54321;
string serviceName = null;
// Not pseudocode :)
var transaction = container.GetService(serviceName, productId, clientId);
What makes this interesting is that despite the number of dependencies you might have, LinFu's IOC container will handle 90% of the boilerplate code for you so you don't have to do all this stuff on your own. The best part is that all the implementations above will all be determined/resolved at runtime.
You can practically swap implementations while the program is running, and you can even replace implementations without even recompiling your application. You can find more info here:
http://www.codeproject.com/KB/cs/LinFu_IOC.aspx
HTH :)
Here's my second take on your questions:
A: In terms of best practice, you can leave the service dependency into the domain object as long as you make sure that you're depending on an interface type. Most (if not all) containers can do that type of injection for you, and it's pretty trivial to mock out each service dependency so you can test every behavior in your concrete classes. I only recommend using abstract classes if you want to refactor out the boilerplate implementation for a particular interface implementation, such as using a base class to do your generic CRUD persistence work.
B and C:
It's good to know that this kind of functionality is available. I suppose a more important question is whether what i'm trying to do is in fact common practice and whether it's considered good practice. i.e.
Have a container resolve and inject dependencies that have been pre-populated >using a persistence framework (e.g. NHibernate) and
Have the container inject concrete implementation of abstract dependencies where the concrete implementation are determined at runtime.
Also, in IoC/DI/NHibernate terminology, does what i'm talking about, have a particular name? Is it, for example, one of the features listed in this comparison or this comparison of .net IoC frameworks? I'd like to read about whether other IoC frameworks (like Castle Windsor) include these functionalities like LinFu does but i don't know whether what i'm describing has a particular name so i don't know what to search for :)
I believe you're actually referring to the comparison posted at this link.
1) AFAIK, it's standard practice to do service injection, but the type of injection that you're referring to would be difficult to do for some of the other frameworks since you have to use domain object IDs to resolve these dependencies at run time, and not all containers support that type of dynamic resolution (aka 'contextual binding'). All things being equal (and assuming that this can be done with the other containers), the only 'best practice' that seems to apply with DI/IoC is that you must use interfaces for your service dependencies.
How these dependencies should be ultimately constructed and resolved should be completely up to you, and in your case, it really doesn't matter if you get these dependencies populated from a persistence framework as long as the container itself is able to eliminate most of the boilerplate resolution code for you.
2) Concrete service injection is standard among DI/IOC frameworks, and most of them can resolve dependencies at runtime; however, these frameworks differ on how and where that injection can be done.
FYI, the two features that you should pay attention to are Constructor Injection and Property Injection. Based on your code examples, I'd say that you'd be more inclined to use constructor injection, so you might want to keep an eye out for how each respective framework does that type of injection for you. HTH :)
Philip,
Thanks for your answer!
B and C:
It's good to know that this kind of functionality is available. I suppose a more important question is whether what i'm trying to do is in fact common practice and whether it's considered good practice. i.e.
Have a container resolve and inject dependencies that have been pre-populated using a persistence framework (e.g. NHibernate) and
Have the container inject concrete implementation of abstract dependencies where the concrete implementation are determined at runtime.
Also, in IoC/DI/NHibernate terminology, does what i'm talking about, have a particular name? Is it, for example, one of the features listed in this comparison or this comparison of .net IoC frameworks? I'd like to read about whether other IoC frameworks (like Castle Windsor) include these functionalities like LinFu does but i don't know whether what i'm describing has a particular name so i don't know what to search for :)
A:
In terms of best practice (i.e. loose coupling, testing etc...), would it be better to remove the service dependency from the domain object or leave it there?
Thanks
Matthew
According to 'Domain Driven Design', your service would be a 'Domain Service', and it's ok for the rest of your domain to call it directly or depend on it.
If you're going to use Nhibernate, check Spring.net, a very popular DI framework that provides you with DAOS, that already have a session injected on them. It also allows you to use declarative transactions (marking methods with attributes). The docs of the project are very very good.
Last but not least, and don't get me wrong, I think you are using the technology just because (I don't see that you have the NEED for DI), this is cool if you're doing it to learn stuff, but wrong in every other case.
Regards
Pablo,
Thanks for you comments.
Maybe if i elaborate a bit more on one area where i intend to use DI within the project (not only, as you say, to learn about DI but also because i think it's necessary) and then further comments can be made as to whether it's the correct place to be using DI.
As mentioned in the original post the application will make use of a MarginCalculator Service:
public abstract class MarginCalculator
{
public abstract double CalculateMargin();
}
Note: the service might be an abstract class or an Interface.
Concrete implementations (components in DI terminology?) will be as follows:
public class ConcreteMarginCalculatorA : MarginCalculator
{
private IDependencyService1 _dependencyService1;
private IDependencyService2 _dependencyService2;
// Constructor dependency injection
public ConcreteMarginCalculatorA(
IDependencyService1 dependencyService1,
IDependencyService2 dependencyService2)
{
this._dependencyService1 = dependencyService1;
this._dependencyService2 = dependencyService2;
}
public override double CalculateMargin
{
// _dependencyService1 and _dependencyService2
// required here to perform calcuation.
}
}
public class ConcreteMarginCalculatorB : MarginCalculator
{
private IDependencyService3 _dependencyService3;
private IDependencyService4 _dependencyService4;
// Constructor dependency injection
public ConcreteMarginCalculatorB(
IDependencyService3 dependencyService3,
IDependencyService4 dependencyService4)
{
this._dependencyService3 = dependencyService3;
this._dependencyService4 = dependencyService4;
}
public override double CalculateMargin
{
// _dependencyService3 and _dependencyService4
// required here to perform calcuation.
}
}
Aren't the concrete Margin Calculators and their construction a perfect example of where dependency injection should be used and how an IoC container can be used to handle the dependency injection?
I think what i'm trying to do is very similar to how DI/IoC are described in articles such as this one and this one.
Finally, i will then use a factory class, possibly with an inner/child container, in order to dynamically resolve components/implementors (ConcreteMarginCalculatorA, ConcreteMarginCalculatorB etc...) based on a parameter value. To achieve this i'm leaning toward Autofac (http://code.google.com/p/autofac/) which allows for selecting an implementor based on a parameter value (http://code.google.com/p/autofac/wiki/ComponentCreation - Section "Selection of an Implementer based on a Parameter Value"):
public class MarginCalculatorFactory
{
private readonly IContainer _factoryLevelContainer;
public MarginCalculatorFactory(IContainer mainContainer)
{
_factoryLevelContainer = mainContainer.CreateChildContainer()
_factoryLevelContainer.RegisterType<MarginCalculator, ConcreteMarginCalculatorA>("ConcMC1");
_factoryLevelContainer.RegisterType<MarginCalculator, ConcreteMarginCalculatorB>("ConcMC2");
}
public MarginCalculator CreateCalculator(string productType)
{
return _factoryLevelContainer.Resolve<MarginCalculator>(productType);
}
}
So that in the end i can do:
marginCalculatorFactory.CreateCalculator(productType);
in the client code and get a fully resolved calculator. The calculator could then in turn be dependency injected into the TransactionProcessor Service:
public class TransactionProcessor
{
private readonly MarginCalculator _marginCalculator;
private readonly Transaction _transaction;
public TransactionProcessor(MarginCalculator marginCalculator
,Transaction transaction)
{
_marginCalculator = marginCalculator;
_transaction = transaction
}
public double CalculateMargin(Transaction t)
{
return _marginCalculator.CalculateMargin(transaction);
}
}
I might be wrong as i'm new to the whole IoC/DI game but it seems to me that this is precisely the kind of scenario that Di/IoC is used for. What do others think?
Thanks
Matthew
Take a look to this post
http://fabiomaulo.blogspot.com/2008/11/entities-behavior-injection.html