1

I have a controller which takes a DbContext and one who does not. I.e.,:

public CalendarController()
{
    var db = new DbContext(); 
    CalendarController(db); // <= Not allowed
}

public CalendarController(IDbContext db)
{
    _calendarManager = new CalendarManager(db);
    _userManager = new UserManager(db);
    _farmingActionManager = new FarmingActionManager(db);
    _cropManager = new CropManager(db);
}

Unfortunately the above gives an error on the CalendarController(db) line:

Expression denotes a 'type', where a 'variable', 'value' or 'method group` was expected

Is it possible to call one constructor from another? I don't want to duplicate all the code.

user2609980
  • 10,264
  • 15
  • 74
  • 143
  • Apparently you're trying to implement Bastard injection anti-pattern. No! don't do that. – Sriram Sakthivel Mar 25 '15 at 20:59
  • @SriramSakthivel Could you explain what Bastard Injection Anti-Pattern is? I am doing it in this way since I need the same instance of DbContext per controller instance, I haven't found a better solution. `autofac` was promising, but it still gave the error of using multiple DbContext instances in one request. – user2609980 Mar 25 '15 at 21:05
  • You're not understanding the DI fully. when you use `new` keyword except in composition root(value objects are exception), then you're violating DI. You're newing up `CalendarManager`, `UserManager` etc, which you should be really taking them as a constructor parameter(as some interface). That said, Bastard Injection is something which occurs when a dependency is Foreign Default(implemented in different assembly) which was injected by default. `DbContext` is a foreign dependency(I believe); you shouldn't be tightly couple the consumer with dependency in another assembly. – Sriram Sakthivel Mar 25 '15 at 21:14
  • 1
    If you really want to become good in dependency injection, I recommend [Mark Seemann's book](http://www.amazon.com/gp/product/1935182501/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1935182501&linkCode=as2&tag=ploeh-20). In fact, I'm reading it right now :) – Sriram Sakthivel Mar 25 '15 at 21:16
  • Look, I had them as constructor parameters at first, but then when doing updates to the database I got the error `An entity object cannot be referenced by multiple instances of IEntityChangeTracker` (see [this SO-question I asked](http://stackoverflow.com/questions/29221881/how-to-use-one-database-context-for-all-instances-that-make-use-of-a-repository)). All managers need the same `DbContext` instance per constructor. How would I accomplish that with injecting all the managers? Where is the starting point? – user2609980 Mar 25 '15 at 21:18
  • I see the answer in your previous question uses [service locator anti-pattern](http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/). It is partially correct; You shouldn't use that either. As a starting point a [sample is here](http://pastebin.com/yg5R1CXZ). You should have got the idea from it. If your concern is Conroller class should have default constructor, then no you can implement [custom controller factory](http://develoq.net/2010/custom-controller-factory-in-asp-net-mvc/). I hope this helps. I'm happy to provide more information. – Sriram Sakthivel Mar 25 '15 at 21:29
  • Please note that having multiple constructors on your services (such as controllers) [is an anti-pattern](https://cuttingedge.it/blogs/steven/pivot/entry.php?id=97). – Steven Mar 25 '15 at 21:45
  • @SriramSakthivel Thanks for the recommendation. I am reading the Mark Seeman book now (a colleague adviced it as well) and see how things could be improved. Now I am using Autofac as a DI-container and inject all managers in the constructors. – user2609980 Apr 18 '15 at 14:24

1 Answers1

7

You have to chain to the constructor like this:

public CalendarController() : this(new DbContext())
{
}

That's the syntax for chaining to any constructor in the same class - it doesn't have to be from a parameterless one to a parameterized one, although it does have to be to a different one :)

Note that this comes before the body of the constructor, so you can't do anything else first, although you can call static methods to compute arguments to the other constructor. You can't use instance methods or properties though. So this is okay:

public Foo() : this(GetDefaultBar())
{
}

public Foo(int bar) { ... }

private static int GetDefaultBar() { ... }

But this isn't:

public Foo() : this(GetDefaultBar())
{
}

public Foo(int bar) { ... }

private int GetDefaultBar() { ... }

The syntax to chain to a constructor in the base class is similar:

public Foo() : base(...)

If you don't specify either : base(...) or : this(...) the compiler implicitly adds a : base() for you. (That doesn't necessarily chain to a parameterless constructor; it could have optional parameters.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @ErwinRooijakkers Jon's answer is full of good information. Good to know. But, since you've tagged the question with dependency injection, I recommend not to do fall in Bastard Injection. Consider my comments just below your post. – Sriram Sakthivel Mar 25 '15 at 21:19