Possible bug with dependency injection on MvvmCross - c#

I'm currently working on a cross platform (Android and iOS) using the brilliant MVVMCross and things are going pretty great with the application and no major hassles so far.
However today I've hit one that's causing me some problems. I'm a strong believer in separation of concerns and what I'm trying to do is to register a class as a lazy singleton implementer of two different interfaces. This is my App.cs in the PCL:
public class App : Cirrious.MvvmCross.ViewModels.MvxApplication
{
public override void Initialize()
{
CreatableTypes()
.EndingWith("Service")
.AsInterfaces()
.RegisterAsLazySingleton();
RegisterAppStart<LoginViewModel>();
Mvx.LazyConstructAndRegisterSingleton<ISystemConfigProviderInitialiser, SystemConfigProvider>();
Mvx.LazyConstructAndRegisterSingleton<ISystemConfigProvider, SystemConfigProvider>();
}
}
The ISystemConfigProvider will have a number of readonly properties only and will be injected into viewmodels that need to read the system config.
The ISystemConfigProviderInitializer will be injected into the DataService (itself constructed by IoC) and has an Initialize() method that allows a poco to be passed in which sets all the properties mentioned for the ISystemConfigProvider
For completeness SystemConfigProvider is like this:
public class SystemConfigProvider: ISystemConfigProvider, ISystemConfigProviderInitialiser
{
public string Name {get;}
....
public string Z {get;}
public void Initialize(PocoObjToSetPropertiesAbove obj)
{
//set all properties
}
}
The problem I'm having is that the SystemConfigProvider class is getting created multiple times. twice, seemingly once per each interface which contradicts what I'm told by the MVVMCross wiki page about Service Location and Inversion of Control:
Technical Note> the lazy singleton implementation here is quite technical - it ensures that if a >class implements IOne and ITwo then the same instance will be returned when resolving both IOne >and ITwo.
If I do away with the ISystemConfigProviderInitialiser interface and lump the Initialize() into the ISystemConfigProvider and only LazyConstructAndRegisterSingleton the ISystemConfigProvider interface then all works fine as far as I can see but it then means that all consumers of ISystemConfigProvider can now see an Initialize() method that they shouldn't see.
I'd greatly appreciate some advice on this.

The problem here is that the Mvx IoC container treats the singleton aspect at the interface level, not the instantiated type. So it doesn't see that SystemConfigProvider is the same type and should only create one instance.
To work around this problem, there are a couple of options:
1) Simply instantiate the singleton at initialization time, then register that singleton for each interface:
var provider = Mvx.IocConstruct(SystemConfigProvider);
Mvx.RegisterSingleton<ISystemConfigProviderInitialiser>(provider);
Mvx.RegisterSingleton<ISystemConfigProvider>(provider);
2) Pass a builder Func to the registration
Mvx.RegisterSingleton(() =>
{
var provider = Mvx.IocConstruct<ISystemConfigProviderInitialiser>();
return provider;
});
Mvx.RegisterSingleton(() =>
{
var provider = Mvx.Resolve<ISystemConfigProviderInitialiser>();
if (provider == null)
{
throw new InvalidOperationException("ISystemConfigProviderInitialiser should be resolved first.");
}
return (ISystemConfigProvider)provider;
});
I'm assuming that the Initialiser should be resolved first, since there is an explicit Initialise() step, so I throw an exception if it is null.
I think Option #1 is probably better. It's simple and explicit.
Hope this helps.

Related

How to register collection of instances in Simple injector

In my project I have more than one database contexts, so I have created a provider for getting the context objects based on need.
My provider is looks like this.
public class DbContextProvider
{
public Func<AccountingContext> AccountingDbContextResolver { get; set; }
public Func<ActiveDirectryContext> ActiveDirectryDbContextResolver { get; set; }
public AccountingContext GetAccountingDbContext() =>
this.AccountingDbContextResolver();
public ActiveDirectryContext GetActiveDirectryDbContext() =>
this.ActiveDirectryDbContextResolver();
}
One ServiceBase class I have created for getting the provider
public class ServiceBase
{
public ServiceBase(DbContextProvider contextProvider)
{
this.ContextProvider = contextProvider;
}
protected DbContextProvider ContextProvider { get; }
public AccountingContext AccountingDbContext =>
this.ContextProvider.GetAccountingDbContext();
public ActiveDirectryContext ActiveDirectryDbContext =>
this.ContextProvider.GetActiveDirectryDbContext();
}
I am using simple injector and I need to create instance of both Database contexts.
For getting the instance I have created two static methods with delegate
private static DbContextProvider CreateActiveDirectryDbContextProvider(Container container)
{
return new DbContextProvider
{
ActiveDirectryDbContextResolver =
() => container.GetInstance<ActiveDirectryContext>();
};
}
private static DbContextProvider CreateAccountingDbContextProvider(Container container)
{
return new DbContextProvider
{
AccountingDbContextResolver = () => container.GetInstance<AccountingContext>();
};
}
And for registrations I have used the below code
var accountingProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(accountingProvider);
var activeDirectryProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(activeDirectryProvider);
If i run the code then I am getting an error like below
System.InvalidOperationException: 'Type DbContextProvider has
already been registered. If your intention is to resolve a collection
of DbContextProvider implementations, use the
Container.Collection.Register overloads. For more information, see
https://simpleinjector.org/coll1. If your intention is to replace the
existing registration with this new registration, you can allow
overriding the current registration by setting
Container.Options.AllowOverridingRegistrations to true. For more
information, see https://simpleinjector.org/ovrrd.'
But everything is working fine when I try with only one context that is ,
var accountingProvider = CreateAccountingDbContextProvider(container);
container.RegisterInstance(accountingProvider);
I have tried to register it using container.Collection.Register, no error is coming but I am not getting the instance in the service layer , I am getting a null reference exception there.
can someone help me to resolve this ?
You only have one type (DbContextProvider) that is responsible for constructing both AccountingContext and ActiveDirectryContext. From that perspective, it is really strange to create two DbContextProvider instances that are each partly initialized. A consumer would not expect GetAccountingDbContext() to return null or throw a NullReferenceException. So instead, you should create one single instance that can be used for both cases:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
container.RegisterInstance<DbContextProvider>(new DbContextProvider
{
ActiveDirectryDbContextResolver = () => container.GetInstance<ActiveDirectryContext>(),
AccountingDbContextResolver = () => container.GetInstance<AccountingContext>()
});
Or better, make DbContextProvider immutable:
container.RegisterInstance<DbContextProvider>(new DbContextProvider(
activeDirectryDbContextResolver: () => container.GetInstance<ActiveDirectryContext>(),
accountingDbContextResolver: () => container.GetInstance<AccountingContext>()));
This fixes the problem, because there is no only one registration for DbContextProvider. This removes the ambiguity, prevents possible bugs, and is a simpler solution.
But while this would work, I would like to suggest a few changes to your design.
Composition over Inheritance
First of all, you should get rid of the ServiceBase base class. Although base classes are not bad per see, when they start to get dependencies of their own, they likely start to violate the Single Responsibility Principle, and their derivatives the Dependency Inversion Principle and the Open/Closed Principle:
Base classes with dependencies often become a hodgepodge of functionality—often cross-cutting concerns. The base class becomes an ever-growing class. Ever-growing classes are an indication of a Single Responsibility Principle violation.
When the base class starts to contain logic, the derivatives automatically depend on that behavior—A derivative is always strongly coupled to its base class. This makes it hard to test the derivative in isolation. In case you ever want to replace or mock the behavior of the base class, it means that its behavior is Volatile. When a class is tightly coupled with a Volatile Dependency, it means you are violating the Dependency Inversion Principle.
The base class's constructor dependencies need to be supplied by the derived class's constructor. This will cause sweeping changes when the base class requires a new dependency, because all derived constructors need to be updated as well.
Instead, of using base classes, do the following:
Instead of forwarding dependencies from the derived class to the base class constructor, the derived class should store the dependency itself in a private field. It can use that dependency directly.
In case the base class contains behavior besides code:
In case that behavior is Volatile, wrap the logic in a class, hide that class behind an abstraction and inject the class (through its abstraction) into the constructor of the derived class. When doing this, it becomes very easy to see what dependencies the derived class has.
In case the behavior is Stable, you can use static helper classes or extension methods to make the base class's behavior reusable.
In case the behavior concerns a cross-cutting concern, consider the use of Decorators or Dynamic Interception as an alternative to base classes.
When you follow this advice, what you end up with is a set of (derived) service classes that depend on a base class that is nothing more than an empty shell. This is when you can remove the base class altogether. What you now achieved is Composition over Inheritance. Composition typically leads to more maintainable systems than inheritance does.
Closure Composition Model
As JoostK mentioned, you can also inject the DbContext types directly into consumers. Whether or not you want to do this, however, depends on the type of composition model you decided to use. What this means is that, when you choose to apply the Closure Composition Model, you should typically inject the DbContext implementations directly into your consumers.
public class ProduceIncomeTaxService : IHandler<ProduceIncomeTax>
{
private readonly AccountingContext context;
// Inject stateful AccountingContext directly into constructor
public ProduceIncomeTaxService(AccountingContext context) => this.context = context;
public void Handle(ProduceIncomeTax command)
{
var record = this.context.AccountingRecords
.Single(r => r.Id == command.Id);
var tax = CalculateIncomeTax(record);
FaxIncomeTax(tax);
this.context.SaveChanges();
}
...
}
This simplifies the registrations of your system, because now you just register the DbContext implementaions and you're done:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
// Of course don't forget to register your service classes.
Interface Segregation Principle
Your current DbContextProvider seems to designed around the Ambient Composition Model. There are advantages of both composition models, and you might have chosen deliberately for the Ambient Composition Model.
Still, however, the DbContextProvider exposes many (10) properties—one for each DbContext. Classes and abstractions with many methods can cause a number of problems concerning maintainability. This stems from the Interface Segregation Principle that prescribes narrow abstractions. So instead of injecting one wide provider implementation that gives access to a single DbContext type. Implementations would typically only require access to a single DbContext type. If they require multiple, the class should almost certainly be split up into smaller, more-focused classes.
So what you can do instead is create a generic abstraction that allows access to a single DbContext type:
public interface IDbContextProvider<T> where T : DbContext
{
T Context { get; }
}
When used in a consumer, this would look as follows:
public class ProduceIncomeTaxService : IHandler<ProduceIncomeTax>
{
private readonly IDbContextProvider<AccountingContext> provider;
// Inject an ambient context provider into the constructor
public ProduceIncomeTaxService(IDbContextProvider<AccountingContext> provider)
=> this.provider = provider;
public void Handle(ProduceIncomeTax command)
{
var record = this.provider.Context.AccountingRecords
.Single(r => r.Id == command.Id);
var tax = CalculateIncomeTax(record);
FaxIncomeTax(tax);
this.provider.Context.SaveChanges();
}
...
}
There are multiple ways to implement IDbContextProvider<T>, but you can, for instance, create an implementation that directly depends on Simple Injector:
public sealed class SimpleInjectorDbContextProvider<T> : IDbContextProvider<T>
where T : DbContext
{
private readonly InstanceProducer producer;
public SimpleInjectorDbContextProvider(Container container)
{
this.producer = container.GetCurrentRegistrations()
.FirstOrDefault(r => r.ServiceType == typeof(T))
?? throw new InvalidOperationException(
$"You forgot to register {typeof(T).Name}. Please call: " +
$"container.Register<{typeof(T).Name}>(Lifestyle.Scope);");
}
public T Context => (T)this.producer.GetInstance();
}
This class uses the injected Container to pull the right InstanceProducer registration for the given DbContext type. If this is not registered, it throws an exception. The InstanceProducer is then used to get the DbContext when Context is called.
Since this class depends on Simple Injector, it should be part of your Composition Root.
You can register it as follows:
container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);
container.Register(
typeof(IDbContextProvider<>),
typeof(SimpleInjectorDbContextProvider<>),
Lifestyle.Singleton);

Using constructor injection when caller expects a specific constructor signature

I'm new to DI in .NET C# & autofac and having problems to understand how to use DI when I can't fully control the caller side.
There are two scenarios I have problems to understand.
Scenario 1: Caller expects a default constructor (without any parameters)
How to handle this scenario when I still want to inject some Service Interfaces when the class is constructed? I was thinking of constructor chaining, but that would mean I have to know the concrete type and it works around the idea of DI. (at least I think).
public class ServiceWorker
{
IService _service;
public ServiceWorker(IService service)
{
_service = service
}
}
public class Caller
{
// No way to change this.
var serviceWorker = new ServiceWorker();
}
Scneario 2: Caller expects a specific constructor signature (e.g.
Same question here. How can I inject additional dependencies when the caller expects an exact match for the constructor signature?
I think my main issue in understanding the concept is, that I don't see how to do DI only partially when not everything is constructed by DI (caller)
public class ServiceWorker
{
IService _service;
public ServiceWorker(string name, string id, IService service)
{
_service = service
}
}
public class Caller
{
// No way to change this.
var serviceWorker = new ServiceWorker(name, id);
}
I know, this is pretty basic, but I believe I need to understand this first before moving on. Are there alternatives?
As Steven correctly points out in his comment, being restricted to a specific constructor signature is an instance of the Constrained Construction anti-pattern. Sometimes, however, that can be outside your control.
An example is the so-called 'Provider pattern', which isn't a pattern at all. In such an example, you may have to play by the rules of a third-party framework, so there isn't much you can do about it. Such frameworks should be considered unfriendly to Dependency Injection.
Consider scenario 2 in the OP, since scenario 1 is just a special case of scenario 2. If you must supply a class with a certain constructor, you could create a Facade that has the required constructor signature. This enables you to avoid polluting your well-designed classes that use Dependency Injection with the constraints imposed by the third-party framework. It could look like this:
public class ServiceWorker
{
IService _service;
public ServiceWorker(string name, string id, IService service)
{
_service = service
}
}
public class ServiceWorkerFacade
{
ServiceWorker imp;
public ServiceWorkerFacade(string name, string id)
{
imp =
new ServiceWorker(
name,
id,
new FooService(
new BarService(),
new BazService());
}
}
public class Caller
{
// No way to change this.
var serviceWorker = new ServiceWorkerFacade(name, id);
}
FooService implements IService. Just to make things interesting, I've assumed that FooService has dependencies of its own, and that those dependencies are satisfied by BarService and BazService.
As Steven suggests, then, you can (from necessity) consider the Facade's constructor the Composition Root.
If you have any opportunity to influence the design of the framework in question, you could point the developers to my guidance on designing DI-friendly frameworks.

Is this implementation of a central static class correct?

So, I'm starting a new project, trying to implement a few things I've learnt over the last few years, the first of which is using Castle for IoC.
I want a central 'Core' class, which would be shared across numerous end projects (Console apps, websites). So I guess, two questions here:
a) Is this approach correct
b) Is my implementation correct.
I know this is a very small class, but I want to get it correct from the start.
public static class Global {
static IWindsorContainer _Container;
static int ContainerInitalised = 0;
static string ServicesFile;
public static IWindsorContainer Container{
get{
if (Interlocked.CompareExchange(ref ContainerInitalised, 1, 0) == 0) {
Collection<IWindsorInstaller> installers = new Collection<IWindsorInstaller> {
{ FromAssembly.InDirectory(new AssemblyFilter("Installers")) }
};
if (!String.IsNullOrWhiteSpace(ServicesFile)) {
installers.Add(Configuration.FromXmlFile(ServicesFile));
}
_Container = new WindsorContainer().Install(installers.ToArray());
}
return _Container;
}
}
public static void Initialise(string servicesFile) {
ServicesFile = servicesFile;
}
}
AS per David your idea go toward a ServiceLocator solution which is the worst way to use an IoC container.
Also abstracting IoC container with a common interface is a bad idea because you end up loosing special container features: speacially an interface not exposing a release method leads to a disaster using a mature IoC container such windosr which is based on RRR pattern.
The correct approach has been clearly described by Krzysztof on his NDC presentations
Plug the IoC container into your app using a factory as per MVC3 implementation
Do one Resolve only as soon as possible: a single Resolve for non web-app, one resolve per request for a web scenario
Release ALWAYS what you resolved
You might be able to clean it up a bit by taking a step toward a "service locator" implementation. (Indeed, there's a common library that does exactly this.)
For example, you can abstract the IoC container behind an interface and have a static factory that provides the current implementation (to replace your generic Global class and make it more targeted). Something like this:
public interface IoCContainer
{
object GetInstance(Type serviceType);
object GetInstance(Type serviceType, string key);
IEnumerable<object> GetAllInstances(Type serviceType);
T GetInstance<T>();
T GetInstance<T>(string key);
IEnumerable<T> GetAllInstances<T>();
}
public static class IoCContainerFactory
{
private static IoCContainer current;
public static IoCContainer Current
{
get
{
if (current == null)
throw new DomainException("IoC Container Not Initialized. This application must call a bootstrap method in an IoC implementation project.");
return current;
}
}
public static void Initialize(IoCContainer container)
{
current = container;
}
}
Then in another project I implement the IoCContainer interface (I use StructureMap, you use Castle... there are plenty of options). Also in that other project I have an Initializer class which will bootstrap the container implementation (since configuration is different for any implementation) and, as a last step, initialize this "global" factory:
IoCContainerFactory.Initialize(new IoCContainerImplementation(ObjectFactory.Container));
(In the case of the above line of code, IoCContainerImplementation is my implementation of the aforementioned interface, and ObjectFactory is from StructureMap and was just configured/bootstrapped in previous lines of code before this one.)
Of course, with this approach, there's a bit of a trade-off. By abstracting my IoC container behind a common interface, I can only do things which are common across many IoC container implementations. For my needs, all I want is to call a method to resolve dependencies. But other things like decorating classes/properties with attributes (if your choice of IoC container has that feature) would require either tightly coupling to that specific container or expanding this implementation to include custom attributes which make use of that feature in some way.

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.

Constructor injection and default overloads

Let's say we have
public interface ITimestampProvider
{
DateTime GetTimestamp();
}
and a class which consumes it
public class Timestamped
{
private ITimestampProvider _timestampProvider
public Timestamped(ITimestampProvider timestampProvider)
{
// arg null check
_timestampProvider = timestampProvider;
}
public DateTime Timestamp { get; private set; }
public void Stamp()
{
this.Timestamp = _timestampProvider.GetTimestamp();
}
}
and a default implementation of:
public sealed class SystemTimestampProvider : ITimestampProvider
{
public DateTime GetTimestamp()
{
return DateTime.Now;
}
}
Is it helpful or harfmful to introduce this constructor?
public Timestamped() : this(new SystemTimestampProvider())
{}
This is a general question, i.e. timestamping is not the interesting part.
I think it depends on the scenario, and is basically a function of who the consumer the code is (library vs. application) and whether you're using an IoC container or not.
If you're using an IoC container, and this is not part of a public API, then let the container do the heavy lifting, and just have the single constructor. Adding the no-args constructor just makes things confusing, since you'll never use it.
If this is part of a public API, then keep both. If you're using IoC, just make sure your IoC finds the "greediest" constructor (the one with the most arguments). Folks not using IoC, but using your API will appreciate not having to construct an entire dependency graph in order to use your object.
If you're not using an IoC container, but just want to to unit test with a mock, keep the no-args constructor, and make the greedy constructor internal. Add InternalsVisibleTo for your unit test assembly so that it can use the greedy constructor. If you're just unit testing, then you don't need the extra public API surface.
i wouldn't provide that constructor. Doing so makes it far too easy to call new TimeStamped and get an instance with new SystemTimestampProvider() when your IoC may be configured to use OtherTimestampProvider().
End of the day you'll end up with one hell of a time trying to debug why you're getting the wrong timestamp.
If you only provide the first constructor you can do a simple find usages of SystemTimestampProvider to find out who is (wrongly) using that provider instead of the IoC configured Provider.
In general I don't think so... It depends on what you're using Dependency Injection for. When I use DI for unit testing, I do the same thing (more or less) by instantiating the production version of the dependant object when the injected instance is null... And then I have an overload that does not take a parameter and delegates to the one that does... I use the parameterless one for production code, and inject a test version for unit test methods...
If you're talking about a IOC container application, otoh, you need to be careful about interfering in what the configuration settings are telling the container to do in a way that's not clear ...
public class EventsLogic
{
private readonly IEventDAL ievtDal;
public IEventDAL IEventDAL { get { return ievtDal; } }
public EventsLogic(): this(null) {}
public EventsLogic(IIEEWSDAL wsDal, IEventDAL evtDal)
{
ievtDal = evtDal ?? new EventDAL();
}
}
I try to avoid this - there are a few places where I've found it to be a useful design but more often than not I've found it just leads to me making mistakes that can be a little puzzling to work out.
The need for the default injected objects is greatly reduced by using a dependency injection container (I use StructureMap) to manage all this wiring - the DI container makes sure that you always get a concrete instance you can use.
The only place where I'm still tempted to use the constructor you suggest is in my unit tests but recently I've been getting far greater value out of using fake or mocked objects.
There are places where having the default dependant objects is the correct and useful design, but in general I'd say that you are just introducing tight coupling that doesn't add a lot of value.
It's neither helpful nor harmful. It poses an aesthetic problem in that you are limiting your DI to constructor injection only when your design may allow for property setter injection.
Another option would be to implement a getter that returns a default implementation:
public DateTime Timestamp
{
get { return _timestampProvider??new SystemTimestampProvider(); }
set { _timestampProvider = value; }
}
Alternately, you can implement the above using a singleton if you're worried about creating too many objects in the heap.
My team has a great deal of success using this method. I recommend one change: Make _timestampProvider readonly. This forces the provider to be deterministic at construction and will eliminate bugs.
public class Timestamped
{
private readonly ITimestampProvider _timestampProvider;
public Timestamped(ITimestampProvider timestampProvider)
{
_timestampProvider = timestampProvider;
}
public Timestamped(): this(new SystemTimestampProvider())
{ }
}
That said, we are always looking at new technologies, including DI frameworks. If we ever abandon this technique for something significantly better I'll let you know.

Categories

Resources