5

seems like with the new unity version has been added support for autowiring.

How many of you are familiar with it and strngly suggest me to use or not use it? Seems to me that the use of it limit my control on the DI especially for what regard the unit tests, am I thinking wrong?

lorenzo.urbini
  • 113
  • 1
  • 10
  • 3
    You may find this relevant: http://blog.ploeh.dk/2012/11/06/WhentouseaDIContainer/ Conceptually, it discusses exactly what you're asking about, although it uses Castle Windsor for its examples instead of Unity. – Mark Seemann Apr 26 '14 at 11:36
  • 2
    In many applications, auto wiring will probably account for the vast majority of component registrations, so you'll only have to take care of ambiguous or more complex cases. When your graph contains dozens or hundreds of objects, full manual registration gets messy to unmanageable. As for unit tests, if the IoC container has anything to do with them, they're either not *unit* tests or you're (**usually**) doing something wrong. If you do need the container for tests, nothing should keep you from overwriting specific registrations made by auto wiring, at least with the containers I know. – TeaDrivenDev Apr 26 '14 at 12:35
  • @MarkSeemann Do you have anything on your blog about autowiring and adapters (or any other pattern when you have 'stacking' of the same interface)? This thing comes pretty often and I've been able to find a 'not-smelling' solution so far. – Hennadii Omelchenko Apr 26 '14 at 13:28
  • If by 'stacking', you mean Decorators, I cover how to do that for six different containers in [my book](http://amzn.to/12p90MG). – Mark Seemann Apr 26 '14 at 13:35
  • @MarkSeemann Yes, that's what I meant. I've read your book, but couldn't find how to 'auto-wire' decorators as named registrations and interceptors don't seem to work in 'autowiring' scenarios. Or am I missing anything? – Hennadii Omelchenko Apr 26 '14 at 13:52
  • For example, Jeremy Miller suggests using semantic interfaces, which seems to be breaking the pattern. – Hennadii Omelchenko Apr 26 '14 at 14:01
  • IIRC, the only container that supports Decorators and Composite OOtB is Castle Windsor, so it's really hard with the other containers. With Windsor, it's easy, because it's built-in. – Mark Seemann Apr 26 '14 at 14:03
  • @HennadiiOmelchenko: Also take a look at [this blog post](http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91) of mine, that describes how generic decorators can be used to apply cross-cutting concerns. – Steven Apr 26 '14 at 14:03
  • 1
    @MarkSeemann: Correction: from all containers, Simple Injector has the best support for applying decorators. Try applying generic decorators conditionally based on predicates or generic type constraints, using partial open generic types, or by applying a factory for the decoratee. All supported OOtB in Simple Injector. – Steven Apr 26 '14 at 14:09
  • @Steven Great article, thanks! And again, if got it right, in fact I can autowire everything but decorators part of my system, and then register decorators manually. – Hennadii Omelchenko Apr 26 '14 at 14:13
  • 2
    @HennadiiOmelchenko: I can only speak for Simple Injector, most components can be auto-wired (especially if they implement some generic interface) and decorators should usually be registered manually. They need manual registration, because the order in which decorators are applied is often crucial for the correctness of your system. – Steven Apr 26 '14 at 14:16
  • @Steven Thanks for the correction. It's been a couple of years since I surveyed the container landscape, and back then, Simple Injector wasn't on my radar :$ – Mark Seemann Apr 26 '14 at 14:16
  • 1
    @MarkSeemann That's completely understandable. Simple Injector gained in popularity (and maturity) long after you finished your book. It might be worth reevaluating it though. Me and the other Simple Injector contributors are happy to discuss anything with you. – Steven Apr 26 '14 at 14:25

2 Answers2

21

I'm assuming that this question is about Auto-Registration, since Unity has had Auto-Wiring for years.

Since I wrote my When to use a DI Container article a couple of years ago, I've only become slightly more radical in my attitude towards DI Containers. In that article, I describe the benefits and trade-offs of using DI Containers, as opposed to Poor Man's DI (manually composing code).

My order of preference is now:

  1. Manually write the code of the Composition Root (Poor Man's DI). This may seem like a lot of trouble, but gives you the best possible feedback, as well as it's easier to understand than using a DI Container.
  2. Use Auto-Registration (AKA Convention over Configuration). While you lose compile-time feedback, the mechanism might actually pull your code towards a greater deal of consistency, because as long as you follow the conventions, things 'just work'. However, this requires that the team is comfortable with the Auto-Registration API of the chosen DI Container, which, in my experience, isn't likely to be the case.
  3. Only use Explicit Register if you have a very compelling reason to do so (and no: not thoroughly understanding DI is not a good reason). These days, I almost never do this, so it's difficult for me to come up with some good cases, but advanced lifetime management may be one motivation.

It's been 1½ years since I last used a DI Container in any production code.

In summary, and in an effort to answer the specific question about Unity:

  • Seriously consider not using Unity at all (or any other DI Container).
  • If you must use Unity, use the Auto-Registration feature. Otherwise, you're likely to get more trouble than benefits from it.

Caveat: I'm writing this as a general response, based on my experience with DI and various DI Containers, including Explicit Registration and Auto-Registration. While I have some knowledge about previous versions of Unity, I don't know anything about the Auto-Registration features of the new version of Unity.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • I'm surprised to see you advocating not using a DI container now since it disagrees with the way I remember your book (and also because it strikes me as a really tedious way to program...). – Casey Apr 26 '14 at 15:43
  • If you are using a DI container I find it hard to imagine anyone *only* using conventions or *only* using explicit registrations but I haven't worked on large teams so maybe I'm just ignorant in that regard. – Casey Apr 26 '14 at 15:49
  • 1
    @emodendroket Parts 1-3 in my book almost exclusively talk about DI without talking about DI Containers at all. Back then, I'd spent most of my career writing code *without* DI Containers, so that's where my experience came from. Then I added part IV to explain how to map those concepts to various containers, because I guessed that would be what readers would want (and I don't think that was a bad guess). I don't believe that the book particularly *endorses* the use of DI Containers, but it also doesn't take as strong a stand against them as I now do; since then, I've learned more... – Mark Seemann Apr 26 '14 at 16:01
  • To be fair, in the article you've linked to above, I suspect using Unity as the DI mechanism would have resulted in much less code than Windsor. FWIW the auto-registration mechanism in Unity 3 isn't bad, although (shameless plug) the Unity Automapper is much, much simpler to use and works for the vast majority of cases with just a single line of code. – Isaac Abraham Apr 26 '14 at 16:17
  • 2
    I don't see a reason _not_ to use a DI Container for anything non trivial. It takes 1 minute to setup one and a few minutes to register some conventions. At most 5 minutes and now you only add new types and they magically work. – MikeSW Apr 26 '14 at 16:18
  • 2
    @MikeSW In my experience, there's one person on the team that understands how that 'magic' works (it used to be me). Everyone else is afraid of it, and it creates a team bottleneck which may not be desirable. Technically, Auto-Registration may be fine, but when you take team dynamics into account, the situation changes. Also, in my experience, the trade from compile-time feedback to run-time feedback often doesn't warrant the slightly easier composition. – Mark Seemann Apr 26 '14 at 16:48
  • 3
    So it's easier to deal with something like " var service=new Service(new Repository( new DbContext( new DbConnection)))" everywhere, instead of the team (clearly juniors) learning and understand a simple concept? What about decoupling, testing then? DI done manually is just hard work waiting to happen. – MikeSW Apr 26 '14 at 16:58
  • 3
    @MikeSW Yes, it's very much easier to deal that sort of code, but it's not *everywhere*, it's only in the [Composition Root](http://blog.ploeh.dk/2011/07/28/CompositionRoot), so the rest (99%) of the application is as loosely coupled and testable as always - you don't need a DI Container for that; [on the contrary](http://stackoverflow.com/a/1465896/126014), I should say... And again, just speaking from my own experience, it's not only juniors who are afraid of DI Container 'magic'. – Mark Seemann Apr 26 '14 at 17:39
  • This implies all the services/repos are instantiated by a factory, right? – MikeSW Apr 26 '14 at 17:47
  • @MikeSW Not really. In a console application, for example, you can just [compose the entire object graph using nested `new` statements](https://github.com/ploeh/Booking/blob/64b7b670fff9560d8947dd133ae54779d867a451/BookingDaemon/Program.cs), so there, you don't need any factories. In ASP.NET MVC, for example, you would need to *implement* `IControllerFactory`, but the implementation [doesn't need any factories](https://github.com/ploeh/Booking/blob/64b7b670fff9560d8947dd133ae54779d867a451/BookingWebUI/PoorMansCompositionRoot.cs). – Mark Seemann Apr 26 '14 at 19:33
  • 2
    Those code samples only convinced me that a DI Container is really the easiest way out. It might be only me, but I find it more difficult to understand and change that code than container type registration. – MikeSW Apr 26 '14 at 19:48
  • 2
    @MikeSW I understand why you would prefer Conventions instead of something like that. The only thing I can say is that, *in my experience*, that's not what most team members want... – Mark Seemann Apr 26 '14 at 20:02
  • @MarkSeemann Yes, but I seem to recall your book saying "I'm using poor man's DI to demonstrate the concept, but there's no reason to do something so tedious in the real world" or something to that effect. Anyway, I'm mostly a one-man show so I don't have to deal with those sorts of team dynamics, but "dumbing down" your design in that way hardly seems desirable... – Casey Apr 27 '14 at 03:30
  • 1
    @emodendroket It may say so somewhere... I don't remember everything I wrote in 500+ pages, but in any case, a written work just represents the author's view at the time it was written. In general, I'm still happy with the book, but there are details, I would change if I were to write it today. In any case, even with Convention over Configuration, I still find a DI Container an unnecessary complication in most code bases (and even if I write a one-man code base). – Mark Seemann Apr 27 '14 at 07:47
  • I didn't mean to suggest you aren't allowed to to change your mind. I was just curious to hear you talk about why, since I found it a surprising position. I still don't think I *agree* but I get what you're saying. :) – Casey Apr 27 '14 at 16:35
  • 1
    Yes, the "magic" code can be daunting to someone unfamiliar with DI frameworks, but it's not rocket science and doesn't take days/weeks to understand. And this is code you touch only a few times per project. On the contrary, adding/removing/rearranging/recomposing dependencies becomes so incredibly easy that even a junior dev can understand it in 5 minutes. And these are things you deal with in your code base every single day. – Phil Sandler Apr 28 '14 at 14:54
  • Yes Mark I was referring to auto-registration and my question was more about why I should use it instead of use a di container or not. In your point 2 you say we should cause we have more consistency instead my opinion I have so far of the feature is that with it we loose the ability to easily debug and the control of registering and resolving whatever we want just as y would do with PMDI. Can you please extend your point and if possible provide an example, thanks. – lorenzo.urbini May 01 '14 at 05:50
  • @lorenzo.urbini The links I provided in the post expand quite a lot on the subject; have you read them? Each of these posts themselves contains many examples, and contain links to other resources that further expand on sub-topics. Is there anything in particular you feel isn't answered yet? – Mark Seemann May 01 '14 at 06:40
  • @Mark Seemann. I am now totally suprised. Because I am reading your book now about: dependency injection in .NET. and you say now that it is better not to use any DI container?? Sorry but can you explain?? You have written a whole book about it with six or seven examples of DI containers – LikeToDo Aug 17 '17 at 13:35
  • @LikeToDo Most of the book (parts 1-3) are about the principles and patterns of DI; they don't hinge on any particular DI Container. Only part 4 of the book is specifically about DI Containers. As explained in the answer here, I've changed my emphasis even more towards [Pure DI](http://blog.ploeh.dk/2014/06/10/pure-di), but the distinction is already there in the book. For the most part, parts 1-3 still hold. – Mark Seemann Aug 17 '17 at 13:44
  • @Mark Seemann. Yes, ok. But so the last part(4) - and for me personal that is a big part of the book is now unnecessary, if I understand you correctly. It is better to write your own DI container? Am I correct? – LikeToDo Aug 17 '17 at 13:55
  • @LikeToDo I never expected part 4 to have the same lifetime as parts 1-3. After all, the book is from 2011, and software evolves. Parts 1-3 are more timeless, and, IMO, where the value of the book lies. And I definitely do not recommend writing your own container; just use [Pure DI](http://blog.ploeh.dk/2014/06/10/pure-di). – Mark Seemann Aug 17 '17 at 14:09
  • @MarkSeemann. Oke, thank you for your feedback. Because I was playing around with castle windsor and unity. And I didnt figure it out by myself that it is better to use pure DI. So that would be mine next step :). So in fact you have helped me to foresee further ahead. – LikeToDo Aug 17 '17 at 14:14
1

I've built a container which automatically register your services. All you need to do is to tag them with an attribute.

this is not autowiring per se, but that's part of my point. Unity have from the start been able to build classes which has not been registered in the container. And that's imho a big weekness as the class might be used with dependencies that it shouldnt use or that it will have a different lifetime than intended.

My choice to use an attribute was to be able to make sure that all services can be resolved and built. When you call the builder.Build() method my container will throw an exception if something can't be resolved.

Hence you will directly at the startup see if something is missing, rather then later at runtime.

So autowiring might seem good, but as you say: You'll loose control only to discover it later during runtime if something is missing.

jgauffin
  • 99,844
  • 45
  • 235
  • 372