TornLifestyle simple injector - c#

I have defined a generic interface like this:
public interface IPlanManagmentRepository<TEntity> where TEntity:class
When I define a concrete implementation like this:
public class ProviderPlanManagementRepo : IPlanManagmentRepository<Provider>
everything works by registering the interface like this:
container.Register(typeof(IPlanManagmentRepository<>),
new [] { typeof(IPlanManagmentRepository<>).Assembly},
Lifestyle.Scoped);
However, If this class also handles more stuff and I add an extra interface:
public interface IProviderPlanManagementRepo
{
void doSomethingSpecificToProviderHere();
}
public class ProviderPlanManagementRepo : IProviderPlanManagementRepo,
IPlanManagmentRepository<Provider>
{
}
Then I get this error:
-[Torn Lifestyle] The registration for IPlanManagmentRepository maps to the same implementation and lifestyle as the registration for IProviderPlanManagementRepo does. They both map to ProviderPlanManagementRepo
I also tried to inherit IPlanManagmentRepository in IProviderPlanManagementRepo but got the same error.
Should this class only handle the implementation from the generic interface?
or is possible to accomplish this with simple injector?

UPDATE:
With the introduction of Simple Injector 4, the container will prevent the creation of multiple Registration instances for the same concrete type in most cases. The Torn Lifestyles warning type should therefore be extremely rare. Torn lifestyles will only happen when a custom lifestyle circumvents the caching behavior of the Lifestyle.CreateRegistration overloads.
Your question is related to this work item and this discussion. Typically, torn lifestyles can be fixed as follows, but Simple Injector 3.1 makes it extraordinary hard to fix violations when types with multiple unrelated interfaces are registered using batch-registration. This is something we will address in one of the coming minor releases.
The easiest fix I can recommend for now is to make your IPlanManagmentRepository<T> registrations transient. You should be able to make them transient, because your components should be immutable any way. So typically only the DbContext should be Scoped, but you might even not want to inject the DbContext into your repositories, since the DbContext is runtime data, and runtime data should not be injected into the components of your object graph.

Related

injecting/resolving generic and none generic services which inherit from same base interface

I have some service classes which inherit all from the same non generic interface.
But some services will not directly inherit it but through some intermediate generic interface.
Using .NET 6
public interface IService { }
public interface IServiceDirect {}
public class ServiceDirect: IServiceDirect {}
public interface IGenericInterface<T>: IService{}
public abstract class AGenericClass<T>: IGenericInterface<T> {}
public class GenericClass: IGenericInterface<MyEntity> {}
I now have the need to get all services which inherit from IService during runtime.
Unfortunately calling _serviceProvider.GetServices<IService>() will only return the services which inherit directly (meaning only through non generic interfaces like ServiceDirect) from IService
Here is how I register the services (assembly is just an Assembly provided through a parameter) and I left out some code to select only the classes/interfaces I want.
assembly.ExportedType.ToList().ForEach(x => {
//services is of type IServiceCollection
services.AddScoped(x.Parent.IsGenericType
? x.Parent.GenericTypeDefinition()
.MakeGenericType(x.Parent.GetGenericArguments())
: x.Parent, x.Class);
}
So far so good, they get injected and can be resolved when constructor injecting them by their most direct interface or abstract parent (exactly what I usually need).
To resolve them with _serviceProvider.GetServices<IService>() I have to add a second registration like this in my ForEach
assembly.ExportedType.ToList().ForEach(x => {
if(x.Parent.IsGenericType)
{
services.AddScoped(x.Parent.GenericTypeDefinition()
.MakeGenericType(x.Parent.GetGenericArguments())
.GetInterfaces().FirstOrDefault(x => x == typeof(IService)),
x.Class);
}
//services is of type IServiceCollection
services.AddScoped(x.Parent.IsGenericType
? x.Parent.GenericTypeDefinition().MakeGenericType(
x.Parent.GetGenericArguments())
: x.Parent, x.Class);
}
Now I can resolve all the services like I need.
My question is: is there a better way instead of registering every interface I need explicitly?
is there a better way instead of registering every interface I need explicitly?
Although your use of Reflection might possibly be simplified a bit, in general, all DI Containers require you to register all types up front.
What you are doing is something that is known as Auto-Registration (a.k.a Batch Registration). Auto-Registration is:
"the ability to automatically register components based on a certain convention in a DI Container by scanning one or more assemblies for implementations of desired abstractions." [Section 12.2.3 of DIPP&P]
Unfortunately, MS.DI does not contain any out-of-the-box functionality for Auto-Registration, which is probably why you are doing this by hand. There's nothing wrong implementing Auto-Registration by hand.
What is also required is making multiple registrations for a single component in case that component needs to be injected/used using multiple interfaces that it implements, as some of your components implement both IService and IGenericInterface<T>. As a general example, consider a class X that implements two interfaces, and application components that need to get injected with both interfaces. That means you'd make the following registration.
class X : IFoo, IBar { }
services.AddTransient<IFoo, X>();
services.AddTransient<IBar, X>();
The only thing you have to be careful about—especially in the context of MS.DI—is to prevent components to get a Torn Lifestyle. The following example, for instance, shows the previous class X getting a Torn Lifestyle:
services.AddSingleton<IFoo, X>();
services.AddSingleton<IBar, X>();
In this case, even though X is registered a singleton, eventually two instances of X will exist in the application; this is typically not the desired behavior and can lead to bugs. This holds for registering components with both the scoped as singleton lifestyles. Transient registration won't have this problem, because new instances are created anyway.
You can prevent this problem by following the advice given here, or in short, when applied to class X:
services.AddSingleton<X>();
services.AddSingleton<IFoo>(sp => sp.GetRequiredService<X>());
services.AddSingleton<IBar>(sp => sp.GetRequiredService<X>());
As a consequence, this does quite complicate your registration process, especially in your case; unfortunately, there's little you can do about it.

SimpleInjector ctor injection mix registered types and simple values

How do I register types which take another registered type as a parameter and also simple types (like an integer)?
public interface IDeviceManager
{
// implementation omitted.
}
public class DeviceManager : IDeviceManager
{
public DeviceManager(IDeviceConfigRepository configRepo, int cacheTimeout)
{
// implementation omitted
}
}
I do have a container registration for the IDeviceConfigRepository. That's ok. But how do I create an instance of DeviceManager with the configured dependency and passing along an integer of my choice in composition root?
I thought about creating a factory.
public class DeviceManagerFactory : IDeviceManagerFactory
{
private readonly Container _container;
public DeviceManagerFactory(Container container)
{
_container = container;
}
public DeviceManager Create(int minutes)
{
var configRepo = _container.GetInstance<IDeviceConfigurationRepository>();
return new DeviceManager(configRepo, minutes);
}
}
This is pretty simple.
However now I do not have a registration for DeviceManager which is the type I ultimately need. Should I change these dependencies to the factory instead?
public class ExampleClassUsingDeviceManager
{
private readonly DeviceManager _deviceManager;
public ExampleClassUsingDeviceManager(DeviceManager deviceManager, ...)
{
_deviceManage = deviceManager;
}
// actions...
}
For this to work and to avoid circular dependencies I would probably have to move the factory from the "application" project (as opposed to class libraries) where the composition root is to the project where the DeviceManager is implemented.
Is that OK? It would of course mean passing around the container.
Any other solutions to this?
EDIT
In the same project for other types I am using parameter objects to inject configuration into my object graph. This works OK since I only have one class instance per parameter object type. If I had to inject different parameter object instances (for example MongoDbRepositoryOptions) into different class instances (for example MongoDbRepository) I would have to use some kind of named registration - which SimpleInjector doesn't support. Even though I only have one integer the parameter object pattern would solve my problem. But I'm not too happy about this pattern knowing it will break as soon as I have multiple instances of the consuming class (i.e. MongoDbRepository).
Example:
MongoDbRepositoryOptions options = new MongoDbRepositoryOptions();
MongoDbRepositoryOptions.CollectionName = "config";
MongoDbRepositoryOptions.ConnectionString = "mongodb://localhost:27017";
MongoDbRepositoryOptions.DatabaseName = "dev";
container.RegisterSingleton<MongoDbRepositoryOptions>(options);
container.RegisterSingleton<IDeviceConfigurationRepository, MongoDbRepository>();
I am excited to hear how you deal best with configurations done at composition root.
Letting your DeviceManagerFactory depend on Container is okay, as long as that factory implementation is part of your Composition Root.
Another option is to inject the IDeviceConfigRepository into the DeviceManagerFactory, this way you can construct a DeviceManager without the need to access the container:
public class DeviceManagerFactory : IDeviceManagerFactory {
private readonly IDeviceConfigurationRepository _repository;
public DeviceManagerFactory(IDeviceConfigurationRepository repository) {
_repository = repository;
}
public DeviceManager Create(int minutes) {
return new DeviceManager(_repository, minutes);
}
}
However now I do not have a registration for DeviceManager which is the type I ultimately need. Should I change these dependencies to the factory instead?
In general I would say that factories are usually the wrong abstraction, since they complicate the consumer instead of simplifying them. So you should typically depend on the service abstraction itself (instead of depending on a factory abstraction that can produces service abstraction implementations), or you should inject some sort of proxy or mediator that completely hides the existence of the service abstraction from point of view of the consumer.
#DavidL points at my blog post about runtime data. I'm unsure though whether the cacheTimeout is runtime data, although you seem to be using it as such, since you are passing it in into the Create method of the factory. But we're missing some context here, to determine what's going on. My blog post still stands though, if it is runtime data, it's an anti-pattern and in that case you should
pass runtime data through method calls of the API
or
retrieve runtime data from specific abstractions that allow resolving runtime data.
UPDATE
In case the value you are using is an application constant, that is read through the configuration file, and doesn't change during lifetime of the application, it is perfectly fine to inject it through the constructor. In that case it is not a runtime value. There is also no need for a factory.
There are multiple ways to register this in Simple Injector, for instance you can use a delegate to register the DeviceManager class:
container.Register<DeviceManager>(() => new DeviceManager(
container.GetInstance<IDeviceConfigRepository>(),
cacheTimeout: 15));
Downside of this approach is that you lose the ability of Simple Injector to auto-wire the type for you, and you disable Simple Injector's ability to verify, diagnose and visualize the object graph for you. Sometimes this is fine, while other times it is not.
The problem here is that Simple Injector blocks the registration of primitive types (because they cause ambiguity) while not presenting you with a clean way to make the registration. We are considering (finally) adding such feature in v4, but that doesn't really address your current needs.
Simple Injector doesn't easily allow you to specify a primitive dependency, while letting the container auto-wire the rest. Simple Injector's IDependencyInjectionBehavior abstraction allows you to override the default behavior (which is to disallow doing this). This is described here, but I usually advice against doing this, because it is usually requires quite a lot of code.
There are basically two options here:
Abstract the specific logic that deals with this caching out of the class and wrap it in a new class. This class will have just the cacheTimeout as its dependency. This is of course only useful when there actually is logical to abstract and is usually only logical when you are injecting that primitive value into multiple consumers. For instance, instead of injecting a connectionstring into multiple classes, you're probably better of injecting an IConnectionFactory into those classes instead.
Wrap the cacheTimeout value into a complex data container specific for the consuming class. This enables you to register that type, since it resolves the ambiguity issue. In fact, this is what you yourself are already suggesting and I think this is a really good thing to do. Since those values are constant at runtime, it is fine to register that DTO as singleton, but make sure to make it immutable. When you give each consumer its own data object, you won't have to register multiple instances of those, since they are unique. Btw, although named registations aren't supported, you can make conditional or contextual registrations using RegisterConditional and there are other ways to achieve named registrations with Simple Injector, but again, I don't think you really need that here.

Resolve more than one object with the same class and interface with Simple Injector

I am trying to migrate from Unity to Simple Injector in my new project. It is so much faster than Unity that I have to give it a shot. I have had a few bumps, but nothing I could not work around. But I have hit another one with "Look-up by Key"
I have read this where the creater of simple injector states his belief that you should not need to resolve more than one class per interface.
I must be a poor programmer, because I have done that with Unity (which supports it very well) and want to do it in my current project.
My scenario is that I have an IRepository interface. I have two separate repositories I want to abstract using the IRepository interface. Like this:
container.Register<FirstData>(() => new FirstData());
container.Register<IRepository>(
() => new GenericRepository(container.GetInstance<FirstData>()));
container.Register<SecondEntities>(() => new SecondEntities());
container.Register<IRepository>(
() => new GenericRepository(container.GetInstance<SecondData>()));
IRepository/GenericRepository is a fairly common abstraction, but you can only have one in SimpleInjector
In Unity I could register both of my repositories and then setup my constructor injection to inject the instance that I needed. This was accomplished using a key for the instance. (I did not need to do a Resolve call in my normal code nor add a dependency to Unity outside my setup.)
With simple injector this does not work. But, for better or worse, the owner of Simple Injector thinks this feature is a bad idea.
NOTE: The author's "in app" system looks like it uses a string key for look-up, but it still requires a different class each time (DefaultRequestHandler, OrdersRequestHandler and CustomersRequestHandler). I just have a GenericRepostory which allows me to abstract my repository methods regardless of what I am connected to.
I suppose I could inherit my GenericRepostory for each time I want to instantiate it. Or have it take a random type parameter that I don't need. But that muddles my design, so I am hoping for another way to do it.
So are there any work arounds that don't have me creating bogus types to differentiate between my two IRepository/GenericRepository instances?
We ended up changing our Generic Repository to look like this:
/// The Type parameter has no funcionality within the repository,
/// it is only there to help us differentiate when registering
/// and resolving different repositories with Simple Injector.
public class GenericRepository<TDummyTypeForSimpleInjector> : IRepository
(We added a type parameter to it).
We then created two dummy classes like this (I changed the names of the classes to match my example):
// These are just dummy classes that are used to help
// register and resolve GenericRepositories with Simple Injector.
public class FirstDataSelector { }
public class SecondDataSelector { }
Then I can register them like this:
container.Register<FirstData>(() => new FirstData());
container.Register(() => new GenericRepository<FirstDataSelector>
(container.GetInstance<FirstData>()));
container.Register<SecondEntities>(() => new SecondEntities());
container.Register(() => new GenericRepository<SecondDataSelector>
(container.GetInstance<SecondData>()));
(Note the generic type param on the GenericRepository and that I do not register it as an IRepository. Those two changes are essential to making this work.)
This works fine. And I am then able to use that registration in the constructor injection of my business logic.
container.Register<IFirstBusiness>(() => new FirstBusiness
(container.GetInstance<GenericRepository<FirstDataSelector>>()));
container.Register<ISecondBusiness>(() => new SecondBusiness
(container.GetInstance<GenericRepository<SecondDataSelector>>()));
Since my Business classes take an IRepository it works fine and does not expose the IOC container or the implementation of my repository to the business classes.
I am basically using the Type parameter as Key for lookup. (A hack I know, but I have limited choices.)
It is kind of disappointing to have to add dummy classes to my design, but our team decided that the drawback was worth it rather than abandoning Simple Injector and going back to Unity.
Your own answer is actually quite good, but its unfortunate that you see the generic type parameter as a dummy; you should make it first class citizen of your design:
public interface IRepository<TData> { }
public clss GenericRepository<TData> : IRepository<TData>
{
public GenericRepository(TData data) { }
}
This way you can simply register them as follows:
container.Register<IRepository<FirstData>, GenericRepository<FirstData>>();
container.Register<IRepository<SecondData>, GenericRepository<SecondData>>();
Your business classes can in that case simply depend on the generic IRepository<FirstData> and IRepository<SecondData> and can simply be registered as follows:
container.Register<IFirstBusiness, FirstBusiness>();
container.Register<ISecondBusiness, SecondBusiness>();
Note how the registrations given here don't use any lambdas. Simple Injector can find this out for you. This makes your DI configuration much simpler, more readable, and especially: more maintainable.
This way you make your design very explicit and unambiguous. Your design was ambiguous because you had a single (non-generic) IRepository interface that should be mapped to several implementations. Although this doesn't have to be bad in all cases, in most cases this ambiguity can and should be prevented, because this complicates your code and your configuration.
Further more, since your generic GenericRepository<T> now maps to the generic IRepository<T> we can replace all Register<IRepository<T>, GenericRepository<T>>() registrations with a single line:
// using SimpleInjector.Extensions;
container.RegisterOpenGeneric(typeof(IRepository<>),
typeof(GenericRepository<>);
To take it even one step further, your business classes could perhaps as well benefit from generic typing. Take a look at this article for instance where each business operation gets its own class but all business operations are hidden behind the same generic ICommandHandler<TCommand> abstraction. When you do this, all business classes can be registered with a single call:
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
typeof(ICommandHandler<>).Assembly);
This call searches the supplied assembly for implementations of the ICommandHandler<TCommand> interface and registers each found implementation in the container. You can add new pieces of business logic (use cases) without having to change the configuration. But this is just one of the many advantages of having such abstraction over your business logic. An other great advantage is that it makes adding cross-cutting concerns (such as logging, transaction handling, security, audit trail, caching, you name it) much easier to implement.

how do IoC this?

I am looking to see how Ioc/Di can simplify wiring the following classes I use often.
Consider a library that has an abstract notion of an Entity and an interface for a data access object:
public abstract class EntityWithTypedId<TId> : IEntityWithTypedId<TId>{...}
public interface IDao<T, TId> where T : IEntityWithTypedId<TId>
For the dao, I have one implementation for NHibernate as well as a fake dao I find useful for testing:
// has an NHib implementation
public class Dao<T, TId> : IDao<T, TId> where T : EntityWithTypedId<TId> {...}
public class DaoFakeBase<T> : IDao<T, int>, IDisposable where T : IEntityWithTypedId<int> {...}
I currently do the following to define an Entity and Dao type for a given project:
/// <summary>
/// <see cref="IEntityWithTypedId{IdT}"/> with an int for an id
/// </summary>
[Serializable]
public abstract class Entity : EntityWithTypedId<int>
{
}
public class Dao<T> : Dao<T, int> where T : Entity
{
protected Dao(ISessionFactory sessionFactory) : base(sessionFactory) { }
}
Can I use a DI tool to define the Entity instead? Can someone show me a code sample of how to do it if so?
Can you also lay out how I might tell my test assembly to use DaoFakes and production to use NHib.Dao
I have been looking at Windsor, mostly because NHibernate contrib projects use it, but am also interested in MEF, AutoFac and Ninject, in that order. I realize that MEF is not an IoC container in the sense that Windsor is. From what I can see with Windsor I would use Installer classes, maybe an EntityInstaller and a DaoInstaller, although I might be missing a FActory type of object here too.
Cheers,
Berryl
UPDATE # KeithS
Are you saying to change something like:
class MyViewModel(IDao<MyClass, int> dao) {...}
becomes something like
class MyViewModel(Func<IDao<MyClass, int>, obj> getDaoFunc) {
_dao = getDaoFunc(this);
}
In your example...
class MyViewModel(IDao<MyClass, int> dao) {...}
...IDao would get resolved at runtime based on a previous registration within your container. The syntax for a Prism/Unity implementation is below...
IUnityContainer.RegisterType<IDao..., DaoFakeBase...>();
The RegisterType takes place within IModule.Initialize() of a given module as defined in the UnityBootstrapper class.
protected override IModuleCatalog GetModuleCatalog()
{
ModuleCatalog catalog = new ModuleCatalog();
catalog.AddModule(typeof(project.Init));
return catalog;
}
You can also register a given type based on a lifetime manager; to behave as a Singleton...
IUnityContainer.RegisterType<IShellController, ShellController>(new ContainerControlledLifetimeManager());
...where the IShellController resolved instance will remain the same returned instance throughout the lifetime of the IUnityContainer.
UPDATE:
Using your code the registration would look like this...
public interface IDao<T, TId> where T : IEntityWithTypedId<TId>
{ }
public class Dao<T, TId> : IDao<T, TId> where T : EntityWithTypedId<TId>
{ }
public class TId
{ }
public abstract class EntityWithTypedId<TId> : IEntityWithTypedId<TId>
{ }
public interface IEntityWithTypedId<TId>
{ }
IUnityContainer.RegisterType<IEntityWithTypedId<TId>, EntityWithTypedId<TId>>();
IUnityContainer.RegisterType<IDao<IEntityWithTypedId<TId>, TId>, Dao<IEntityWithTypedId<TId>, TId>>();
IDao<IEntityWithTypedId<TId>, TId> dao = IUnityContainer.Resolve<IDao<IEntityWithTypedId<TId>, TId>>();
I would not use IoC to register the relationship between DAOs and their types (which is basically what you'd be doing). This will lead to you using the IoC container as a "service locator", a known anti-pattern where you pass the IoC container into objects that will use it to get the DAO they need.
I think the best way to simplify this from a consumption perspective would be to define a strategy pattern, using a factory class or method:
public Dao<T, TId> GetDaoFor<T, TId>(T objectInstance) where T:EntityWithTypedId<TId>
{
//Here, you could use a Dictionary, Linq with some reflection, etc.
}
This one method can be injected as a delegate into classes dependent upon DAOs. The difference is that classes that need a DAO are dependent on a method that can give it to them, which can be provided by the IoC container; they are NOT dependent on the container itself (which is the primary source of evil inherent in the "service locator" pattern). This reduces the number of things you'd have to change if you re-wrote how you got these DAOs.
EDIT: A bit off-topic, but I opened the door:
The service location pattern is generally to be avoided, because it results in code that relies on the service locator. For instance, the following is common in code where the IoC has been exposed at child levels:
private IDependency _dependency;
public IDependency MyDependency
{
get {
_dependency = _dependency ?? IoC.Resolve<IDependency>();
return _dependency;
}
}
While this seems like a nice pattern (dependencies are lazily initialized, consuming code doesn't need to know about dependencies of the child, and you always* get a reference), this code will ALWAYS require the IoC singleton to exist. You can change the IoC framework behind it, you can remove the third-party tool altogether and roll your own, but this class will always require something on which to statically call Resolve<IDependency>().
You also don't ALWAYS get a reference; you get a reference only if you properly registered IDependency with IoC. This produces two more weaknesses; 1) you don't know what the class will need without opening it up, and 2) if/when the call fails, it will fail deep in the bowels of the dependent class' inner workings. If you develop a new class, and plug it into IoC, it may pass integration, and even work in production for a while, until you start getting weird "object reference set to null" errors in really weird places in code, which are, trust me, a nightmare to debug.
Lastly, unit-testing service-locator-pattern code is more difficult, for the simple reason that you must mock the service locator as well as the dependency provided by the service locator. You can leave the production service locator in use, and simply register mocked classes as the dependencies, but that's not a unit test; the test relies on, and thus to some extent tests, that the integration of the class and its service locator works as expected. That's an integration test.
By contrast, dependency injection patterns free you from any dependency on how dependencies are resolved. The only requirement (in constructor-injection) is that they be around when the class is created. This has several advantages:
If not using an IoC framework, you have to know what the class will need to instantiate it.
If using an IoC framework, you get a runtime error when attempting to instantiate the dependent class, not sometime later when the object actually gets resolved.
When testing a dependent class, you can more easily mock the dependency, because the dependency does not have to be fed in via the service locator.
You can in most IoC frameworks still lazily initialize dependencies by providing a factory method instead of the actual dependency to the constructor. The above pattern then calls that delegate, which could come from anywhere, instead of a static named method which is satisfied by one and only one construct in the entire codebase.

Enforcing dependencies in IoC via a constructor?

I'm trying to come to terms with using IoC/Dependency Injection while at the same time programming to contracts rather than specific classes. The dilemma I'm having is the tension between:
Do program to interfaces for IoC: I started out with IoC relying heavily on interfaces. Judging by Spring's sample projects, interfaces are the way to go when programing to a contract with IoC.
( ... although abstract classes generally preferred: the main drawback of interfaces is that they are much less flexible than classes when it comes to allowing for evolution of APIs )
Do make class dependencies explicit via constructor
My gut feeling is that it's good programming practice to pass dependencies in to a class's constructor. Indeed, this is dependency injection.
... except you can't enforce constructor signature in interfaces/abstract clases: Neither interfaces or nor abstract classes allow for defining a constructor signature ( easily / elegantly ).
See also Framework Design Guidelines section 4.4: DO NOT define public or protected internal constructors in abstract types. ... Constructors should be public only if users will need to create instances of the type.
This question is related to a previous stackoverflow question: Interface defining a constructor signature?
But my question is:
Since you can't define a constructor in a C# interface/abstract class, as the question above asks, on a practical level:
How do you reconcile this with the sensible practice of passing dependencies in via a constructor?
Edit: Thank you for the answers. I'm hoping for some insight on what I should do in this case. Just not use contructor args? Use some sort of Init() method that does take the dependencies?
Edit2: Thanks for the great answers, very helpful.
I always think this is easier to explain with a (made up) example...
Imagine you have an ICustomerRepository interface, an IShoppingCartRepository interface and an ICheckout interface. You have concrete implementations of those interfaces - CustomerRepository, ShoppingCartRepository, and CheckoutService.
Your CheckoutService concrete class has a constructor that takes an ICustomerRepository and an IShoppingCartRepository - e.g.
public CheckoutService(ICustomerRepository customerRepository, IShoppingCartRepository shoppingCartRepository)
{
// Set fields for use in some methods later...
_customerRepository = customerRepository;
_shoppingCartRepository = shoppingCartRepository;
}
Then, when you want an ICheckoutService implementation to do some work with, you tell your IoC container which concrete class it should use for each interface type and ask it to build you an ICheckoutService. Your IoC container will go and build your classes for you, injecting the correct concrete classes into the constructor of your CheckoutService. It will also build dependencies all the way down the class heirarchy here, so if, for example your ShoppingCartRepository takes an IDatabaseSession interface in the constructor, your IoC container will inject that dependency too, as long as you have told it which concrete class to use for your IDatabaseService.
Here's some code you might use when configuring (for example) StructureMap as your IoC container (this code would typically be called during app startup):
public class AppRegistry : Registry
{
public AppRegistry()
{
ForRequestedType<ICheckoutService>().TheDefaultIsConcreteType<CheckoutService>();
ForRequestedType<ICustomerRepository>().TheDefaultIsConcreteType<CustomerRepository>();
// etc...
}
}
Then to get an instance of ICheckoutService built up and ready to go, with all the dependencies passed into the constructor for you, you would use something like:
var checkoutService = ObjectFactory.GetInstance<ICheckoutService>();
I hope that makes sense!
Your IoC container must construct an object from a concrete type, even though what you're passing around is an interface. Your constructor is not a behavior or state contract, so it does not belong in an interface or as a public member of your abstract class.
A constructor is an implementation detail, so you do not need to separate its definition from the concrete class.
You cannot define constructor signatures in interfaces. That wouldn't make sense anyway since the interface shouldn't enforce how the implementations are constructed.
Abstract classes though can indeed have constructors. They must be protected since public constructors does not make sense either. They should only be called by concrete subclasses.
The IoC principle dictates that instead of having class A know about and instantiate class B, you should instead pass in a reference to IB to the constructor of A. Then A will not need to know about class B and thus you can easily substitute class B with some other implementation of IB.
Since you're passing in an already instantiated object of class B, the IB interface doesn't need to have a constructor signature.

Categories

Resources