Unity - DependencyAttribute or Interface Inheritance for constructor injection - c#

What is suggested practice regarding constructor injection with Unity?
What of next two examples is better practice from DI point of view? Is there better solution?
(These examples are simple illustrations)
public interface ICircle
{
double Radius{get;set;}
}
Container.RegisterType<ICircle, SmallCircle>("Small");
Container.RegisterType<ICircle, BigCircle>("Big");
public class Bike{
Public Bike([Dependency("Big") ICircle bigCircle, Dependency("Small") ICircle smallCircle) { }
}
Or this, more strongly typed solution...
public interface IBigCircle : ICircle
{
// **Empty interface**
}
Container.RegisterType<ICircle, SmallCircle>();
Container.RegisterType<IBigCircle, BigCircle>();
public class Bike{
Public Bike( IBigCircle bigCircle, ICircle smallCircle) { }
}
What worries me is that number of empty interfaces can grow over the time in this second solution.

IMO, the first code sample is better than the first because it is not cluttering the design with unnecessary interfaces (e.g. IBigCircle). However, both examples are not great. The problem with the first sample is that using the DependencyAttribute couples the container to the application which is something to avoid.
So if the two examples are not great than what is a better alternative?
Here are a few. The first alternative is to use an InjectionFactory to instantiate the required object:
IUnityContainer container = new UnityContainer();
container.RegisterType<ICircle, SmallCircle>("Small");
container.RegisterType<ICircle, BigCircle>("Big");
container.RegisterType<Bike>(new InjectionFactory(
c => new Bike(c.Resolve<ICircle>("Big"), c.Resolve<ICircle>("Small"))));
In the above example the container is used to resolve the "Big" and "Small" registered ICircle implementations. Also, because we use new Bike we get compile time checking of the constructor arguments.
Another similar approach is to use an InjectionConstructor to specify the objects to inject:
container.RegisterType<Bike>(new InjectionConstructor(
new ResolvedParameter<ICircle>("Big"),
new ResolvedParameter<ICircle>("Small")
));
The above tells Unity to use the Constructor with two ICircle Parameters and the ResolvedParameter indicates to resolve the specific ICircle by name.
Another approach you could use (but probably wouldn't be the first choice but is included here for completeness) is to specify what types are required at resolve time instead of registration time:
container.Resolve<Bike>(
new ParameterOverride("bigCircle", container.Resolve<ICircle>("Big")),
new ParameterOverride("smallCircle", container.Resolve<ICircle>("Small")));

The example carries some assumptions with it. For example, it's suggested from reading the interface names that IBigCircle would have a larger radius than ISmallCircle but that depends on the implementation, not on the name of the interface. The interfaces can't guarantee what their names imply. (Just like IEnumerable<string> bigList, IEnumerable<string> smallList can't really enforce which is bigger.)
If what matters is that one is bigger than the other you could just depend on two ICircles and determine at runtime which is bigger. Or you could have an IWheels interface consisting of two ICircles and use some sort of factory to create acceptable pairs of circles out of available implementations.

In the first approach, your classes know the name of the dependencies that would be injected into them. So this code:
[Dependency("Big")] ICircle bigCircle
Is not very much different from:
bigCircle = ServiceLocator.Locate<ICircle>("Big");
This is the service locator anti-pattern.
Your class is basically guiding the container to inject a dependency with a specific name. It is involved in the composition process. When doing proper dependency injection, classes should have a passive role only.
Your second approach is an attempt to solve this problem by introducing yet another interface that represents the same abstraction just to please the container. What happens if you have a decorator for ICircle, do you have to create a similar decorator for IBigCircle?
A better approach is to do dependency injection without a container. This is called Pure DI. See this article for a related discussion. Pure DI is specially useful when you have multiple implementations of a single interface (which is true in many applications).

Related

ServiceStack IoC/DI: Registering classes in the Container - how to register all that implements a specific interface

I have started looking into ServiceStack IoC/DI more closely, and it is working very nicely so far, when I for example use the manual registration approach:
container.AddScoped<IGeoService, GeoService>();
My property in the Service is then populated as expected:
public class MyNiceService : Service
{
public IGeoService Geo { get; set; }
}
The above works and Geo is populated correctly.
The first thoughts are:
Why is there an option to specify both the Interface and the concrete class?
If I just add it to the container using container.AddScoped<GeoService>(); then it should 'fit' the property, because GeoService implements the IGeoService?
However, if I use container.AddScoped<GeoService>();, then, the DI fails, and my IGeoService property in the Services is null.
If I change the property to public GeoService Geo { get; set; }, then the DI works.
Auto-register all classes that implements an interface
Preferably, I would like to find all classes that implements a specific Interface, and register all of those classes in the container, something like:
GetType().Assembly.GetTypes()
.Where(x => x is IMyCoreService && x.IsClass && !x.IsAbstract)
.Each(x => container.RegisterAutoWiredType(x));
but this fails, the public GeoService Geo { get; set; } is then null.
I appreciate some input, so I am doing things the correct way :-)
Not a true answer, but rather a partial answer focused on "Why is there an option to specify both the Interface and the concrete class?".
(Counter)example
Imagine that in addition to your current code you also have this class:
public class OtherGeoService : IGeoService { ... }
and this DI setup:
container.AddScoped<GeoService>();
container.AddScoped<OtherGeoService>();
Then the question becomes "instance of which class should be injected as IGeoService?". This question has no easy answer from the DI framework perspective (albeit it might from your perspective), and that is why in most frameworks it is your responsibility to answer that question. So by writing
container.AddScoped<IGeoService, GeoService>();
you're basically saying "if someone asks for IGeoService, give them a GeoService".
Second side of the same coin
On the other hand, many classes that people usually register in DI containers implement various common interfaces like IEnumerable, IDisposable or ISerializable. If there were some elaborate implementation selection algorithms in action1, it would be very hard to determine (or at least not apparent) what exact type of object will be injected.
Recap
I believe that these are two main reasons for why most (if not all) DI frameworks require such "verbose" dependency registration. You only get exactly what you ask for, and not "the next best thing that technically 'fits' your requirements". Note that the decision is not controlled by the requesting code, so the IoC paradigm is not violated.
OK, but WHY?
I understand that it might seem over-engineered for day-to-day use to a developer at the beginning of their journey into the programming world. I mean, it is completely reasonable to ask "why would I ever provide more than one implementation of a service?", which boils down to "why would I bother defining all those boilerplate interfaces if they're going to only have one implementation?".
In many (perhaps even most) cases you wouldn't have to. But there are good reasons to do it anyway:
It stems from the "O" in SOLID programming principles. An interface only provides an abstraction of "what a service can do" and not "how exactly does it do it". That way your services are clearly separated in terms of their business logic. At first it may seem unlikely, but there's a good chance that at some point you will be required to modify/replace parts of the application to suit new needs.
It comes in very handy when writing unit tests. You can easily mock a dependency if it is an interface. It is far more messy (if at all possible) to mock concrete classes for testing purposes.2
1 It is my personal opinion that no such algorithms should be in place, or at least you should try not to depend on them. That way you can almost painlessly switch the DI framework along the way without any side effects.
2 It is widely believed that unit testing should not affect the design of the tested unit, i.e. you should not introduce a dependency or expose any functionality solely to allow or simplify its testing.
When you register your dependency, it's always being registered it against a type. If you don't specify an interface then it will register it against its concrete Type which you would need to use in in your dependency properties. Likewise if you register the dependency against its interface you would need to use the interface in your dependency properties instead.
There's no implied behavior that registers a concrete type against all its interfaces it implements, what ever type it's registered against is the type you need to use to resolve it.
If you register a concrete dependency with:
container.RegisterAutoWiredType(typeof(GeoService));
Then it will get injected in Services that reference its concrete Type property:
public GeoService Geo { get; set; }
If you're saying it doesn't then I'm assuming your query isn't registering the type.

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.

Is there an alternative to bastard injection? (AKA poor man's injection via default constructor)

I most commonly am tempted to use "bastard injection" in a few cases. When I have a "proper" dependency-injection constructor:
public class ThingMaker {
...
public ThingMaker(IThingSource source){
_source = source;
}
But then, for classes I am intending as public APIs (classes that other development teams will consume), I can never find a better option than to write a default "bastard" constructor with the most-likely needed dependency:
public ThingMaker() : this(new DefaultThingSource()) {}
...
}
The obvious drawback here is that this creates a static dependency on DefaultThingSource; ideally, there would be no such dependency, and the consumer would always inject whatever IThingSource they wanted. However, this is too hard to use; consumers want to new up a ThingMaker and get to work making Things, then months later inject something else when the need arises. This leaves just a few options in my opinion:
Omit the bastard constructor; force the consumer of ThingMaker to understand IThingSource, understand how ThingMaker interacts with IThingSource, find or write a concrete class, and then inject an instance in their constructor call.
Omit the bastard constructor and provide a separate factory, container, or other bootstrapping class/method; somehow make the consumer understand that they don't need to write their own IThingSource; force the consumer of ThingMaker to find and understand the factory or bootstrapper and use it.
Keep the bastard constructor, enabling the consumer to "new up" an object and run with it, and coping with the optional static dependency on DefaultThingSource.
Boy, #3 sure seems attractive. Is there another, better option? #1 or #2 just don't seem worth it.
As far as I understand, this question relates to how to expose a loosely coupled API with some appropriate defaults. In this case, you may have a good Local Default, in which case the dependency can be regarded as optional. One way to deal with optional dependencies is to use Property Injection instead of Constructor Injection - in fact, this is sort of the poster scenario for Property Injection.
However, the real danger of Bastard Injection is when the default is a Foreign Default, because that would mean that the default constructor drags along an undesirable coupling to the assembly implementing the default. As I understand this question, however, the intended default would originate in the same assembly, in which case I don't see any particular danger.
In any case you might also consider a Facade as described in one of my earlier answers: Dependency Inject (DI) "friendly" library
BTW, the terminology used here is based on the pattern language from my book.
My trade-off is a spin on #BrokenGlass:
1) Sole constructor is parameterized constructor
2) Use factory method to create a ThingMaker and pass in that default source.
public class ThingMaker {
public ThingMaker(IThingSource source){
_source = source;
}
public static ThingMaker CreateDefault() {
return new ThingMaker(new DefaultThingSource());
}
}
Obviously this doesn't eliminate your dependency, but it does make it clearer to me that this object has dependencies that a caller can deep dive into if they care to. You can make that factory method even more explicit if you like (CreateThingMakerWithDefaultThingSource) if that helps with understanding. I prefer this to overriding the IThingSource factory method since it continues to favor composition. You can also add a new factory method when the DefaultThingSource is obsoleted and have a clear way to find all the code using the DefaultThingSource and mark it to be upgraded.
You covered the possibilities in your question. Factory class elsewhere for convenience or some convenience within the class itself. The only other unattractive option would be reflection-based, hiding the dependency even further.
One alternative is to have a factory method CreateThingSource() in your ThingMaker class that creates the dependency for you.
For testing or if you do need another type of IThingSource you would then have to create a subclass of ThingMaker and override CreateThingSource() to return the concrete type you want. Obviously this approach only is worth it if you mainly need to be able to inject the dependency in for testing, but for most/all other purposes do not need another IThingSource
I vote for #3. You'll be making your life--and the lives of other developers--easier.
If you have to have a "default" dependency, also known as Poor Man’s Dependency Injection, then you have to initialize and "wire" the dependency somewhere.
I will keep the two constructors but have a factory just for the initialization.
public class ThingMaker
{
private IThingSource _source;
public ThingMaker(IThingSource source)
{
_source = source;
}
public ThingMaker() : this(ThingFactory.Current.CreateThingSource())
{
}
}
Now in the factory create the default instance and allow the method to be overrided:
public class ThingFactory
{
public virtual IThingSource CreateThingSource()
{
return new DefaultThingSource();
}
}
Update:
Why using two constructors:
Two constructors clearly show how the class is intended to be used. The parameter-less constructor states: just create an instance and the class will perform all of it's responsibilities. Now the second constructor states that the class depends of IThingSource and provides a way of using an implementation different than the default one.
Why using a factory:
1- Discipline: Creating new instances shouldn't be part of the responsibilities of this class, a factory class is more appropriate.
2- DRY: Imagine that in the same API other classes also depend on IThingSource and do the same. Override once the factory method returning IThingSource and all the classes in your API automatically start using the new instance.
I don't see a problem in coupling ThingMaker to a default implementation of IThingSource as long as this implementation makes sense to the API as a whole and also you provide ways to override this dependency for testing and extension purposes.
You are unhappy with the OO impurity of this dependency, but you don't really say what trouble it ultimately causes.
Is ThingMaker using DefaultThingSource in any way that does not conform to IThingSource? No.
Could there come a time where you would be forced to retire the parameterless constructor? Since you are able to provide a default implementation at this time, unlikely.
I think the biggest problem here is the choice of name, not whether to use the technique.
The examples usually related to this style of injection are often extremely simplisitic: "in the default constructor for class B, call an overloaded constructor with new A() and be on your way!"
The reality is that dependencies are often extremely complex to construct. For example, what if B needs a non-class dependency like a database connection or application setting? You then tie class B to the System.Configuration namespace, increasing its complexity and coupling while lowering its coherence, all to encode details which could simply be externalized by omitting the default constructor.
This style of injection communicates to the reader that you have recognized the benefits of decoupled design but are unwilling to commit to it. We all know that when someone sees that juicy, easy, low-friction default constructor, they are going to call it no matter how rigid it makes their program from that point on. They can't understand the structure of their program without reading the source code for that default constructor, which isn't an option when you just distribute the assemblies. You can document the conventions of connection string name and app settings key, but at that point the code doesn't stand on its own and you put the onus on the developer to hunt down the right incantation.
Optimizing code so those who write it can get by without understanding what they are saying is a siren song, an anti-pattern that ultimately leads to more time lost in unraveling the magic than time saved in initial effort. Either decouple or don't; keeping a foot in each pattern diminishes the focus of both.
For what it is worth, all the standard code I've seen in Java does it like this:
public class ThingMaker {
private IThingSource iThingSource;
public ThingMaker() {
iThingSource = createIThingSource();
}
public virtual IThingSource createIThingSource() {
return new DefaultThingSource();
}
}
Anybody who doesn't want a DefaultThingSource object can override createIThingSource. (If possible, the call to createIThingSource would be somewhere other than the constructor.) C# does not encourage overriding like Java does, and it might not be as obvious as it would be in Java that the users can and perhaps should provide their own IThingSource implementation. (Nor as obvious how to provide it.) My guess is that #3 is the way to go, but I thought I would mention this.
Just an idea - perhaps a bit more elegant but sadly doesn't get rid of the dependency:
remove the "bastard constructor"
in the standard constructor you make the source param default to null
then you check for source being null and if this is the case you assign it "new DefaultThingSource()" otherweise whatever the consumer injects
Have an internal factory (internal to your library) that maps the DefaultThingSource to IThingSource, which is called from the default constructor.
This allows you to "new up" the ThingMaker class without parameters or any knowledge of IThingSource and without a direct dependency on DefaultThingSource.
For truly public APIs, I generally handle this using a two-part approach:
Create a helper within the API to allow an API consumer to register "default" interface implementations from the API with their IoC container of choice.
If it is desirable to allow the API consumer to use the API without their own IoC container, host an optional container within the API that is populated the same "default" implementations.
The really tricky part here is deciding when to activate the container #2, and the best choice approach will depend heavily on your intended API consumers.
I support option #1, with one extension: make DefaultThingSource a public class. Your wording above implies that DefaultThingSource will be hidden from public consumers of the API, but as I understand your situation there's no reason not to expose the default. Furthermore, you can easily document the fact that outside of special circumstances, a new DefaultThingSource() can always be passed to the ThingMaker.

How does this "Programming to Interfaces" thing work?

I like the idea of "programming to interfaces" and avoiding the use of the "new" keyword.
However, what do I do when I have two classes that have the same interface but are fundamentally different to set up. Without going into detail about my specific code, I have an interface with a method, "DoStuff". Two classes implement this interface. One is very simple and requires no initialisation to speak of. The other has five different variables that need to be set up. When combined, they allow for literally millions of ways for the class to work when DoStuff is called.
So when do I "new" these classes? I though about using factories but I don't think they are suitable in this case because of the vast difference in setup. (BTW: there are actually about ten different classes using the interface, each allowing the formation of part of a complex pipeline and each with different configuration requirements).
I think you may be misunderstanding the concept of programming to interfaces. You always have to use the new keyword in object oriented languages to create new instances of objects. Just because you program to interfaces doesn't remove that requirement.
Programming to an interface simply means that all your concrete classes have their behavior defined in an interface instead of in the concrete class itself. So when you define the type of a variable, you define it to be the interface instead of a concrete type.
In your case, just implement DoStuff in your concrete classes as each class needs it implemented (whether doing it simply or with 10 other initialized objects and setup). For example, if you have an interface IInterface and class SomeClass which implements IInterface. You might declare an instance of SomeClass as such:
IInterface myInstance = new SomeClass();
This allows you to pass this instance around to other functions without having to have those functions worry about the implementation details of that instance's class.
Well you really have 3 options. Use new, use a factory or use an DI container. With a DI container your five variables would most likely need to be in a configuration file of some sorts.
But to be completely honest it sounds like you're making your life harder than it needs to be by forcing yourself into a corner. Instead of coding to some ideal, rather code in a manner which best facilitates solving the problem at hand. Not saying you should do a hack job of it, but really, saying you don't want to use new, that is really making your life harder than it needs to be...
Regardless of what you use, at some point you're going to have to construct instances of your classes in order to use them, there's no way around that.
How to go about doing that depends on what you want to accomplish, and the semantics of those classes.
Take the class you mention with those fields.
Can those fields be read from somewhere? A configuration file, as an example? If so, perhaps all you need is just a default constructor that initializes those fields from such a configuration file.
However, if the content of those fields really needs to be passed in from the outside world, there's no way around that.
Perhaps you should look at a IoC container and Dependency Injection?
If you are passing that many configuration parameters into your class it may have too many responsibilities. You should look into breaking it up into smaller classes that only have a single responsibility.
Avoiding the new keyword can be valuable because it creates a dependancy on the implementing class. A better solution would be to use Dependancy Injection.
for example
public interface IDoStuff
{
void DoStuff();
}
public class DoStuffService
{
private IDoStuff doer;
public DoStuffService()
{
//Class is now dependant on DoLotsOfStuff
doer = new DoLotsOfStuff(1,true, "config string");
}
}
public class DoStuffBetterService
{
private IDoStuff doer;
//inject dependancy - no longer dependant on DoLotsOfStuff
public DoStuffBetterService(IDoStuff doer)
{
this.doer = doer;
}
}
Obviously you still have to create the IDoStuff object being passed in somewhere.
An Inversion of Control (IoC) container is a good tool to help with implementing this.
Here is a good tutorial for Castle Windsor Container if you are interested in learning more. (There are many other IoC containers, I just happen to use this one.)
The example in your question was very abstract, so I hope this answer is helpful.
If I understand you correctly the problem is with different initialization. You need to provide for two classes that have the same interface. One does not need anything, and the other needs some paramaters and calls some complex initialization.
You should use have a constructor that gets InitializationParameter. Both classes should get it. One with a simple interface that does not need to get anything from it. The other that needs params and will get them from it.
If you are concerned about initialization you can use factory, just ask it for some interface providing this init parameter and factory will create, init and return to you the object according to the values you provided.
If something is not clear - please ask.

Categories

Resources