Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've been thinking a bit on how dependency injection could be better integrated directly into a C# like language. I've come up with a potential solution I'd like to hear your opinion on. I haven't used many dependency injection frameworks so there might be something I'm overlooking

Anyways, the idea is the be able to declare properties as "injectable" using a keyword. When an object is instantiated and that property is not initialized through the constructor or object initializer it requests an instance of that property type from some global service.

Similarily you register handlers for different types to that service so that you can instantiate the injected property type.

The upside of using this kind of architecture IMO is that it's fairly flexible and easy to use. The downside is that there might be some overhead of doing the callout to the singleton each time you initiate a class that has injection.

Then again that's only an issue for classes that get's instantiated frequently in a high performance solution so it shouldn't be much of an issue. Perhaps you could use some kind of factory in those instances.

Thought, issues, questions, better ideas?

Code

public class SomeClass
{

  public SomeClass()
  {
     //implicit behavior if Animal is not set in constructor or initializer
    this.Animal =  GlobalInjector.Get(this,typeof(Mammal))

  }

  public injectable Mammal Animal  
  {
   get;
   set;
  }
}


 GlobalInjector.Register(typeof(Mammal), () => return new Mammal(someParameter));
share|improve this question
    
Could you give a pseudo code example for those of us that is not to familiar with DI? PS. Maybe you can answer my question regarding DI as well? :) –  Steven Mar 30 '11 at 7:43
2  
I'm not sure I get it. You can get all that with a global DI container and an '[Injectable]' attribute instead of a keyword, right? –  nikie Mar 30 '11 at 7:55
    
Hi, I tried writing a bit about DI on your question, not sure it answers it though –  konrad Mar 30 '11 at 8:05
    
nikie: Yeah sure, I guess you could implement the actual mechanism in different ways, I'm more interested if the underlying logic is sound –  konrad Mar 30 '11 at 8:06
    
So what is different between this and existing IoC other than your extra keyword? –  Matthew Whited Mar 30 '11 at 13:14
show 3 more comments

4 Answers

Have you seen the Managed Extensibility Framework that comes with .NET 4? Here's an article I wrote with some examples. Basically it's a form of dependency injection built into .NET, with the added features of run-time discoverability.

Property injections look like this:

class Program
{
    [Import]
    public IMessageSender MessageSender { get; set; }
}

Constructor injections look like this:

class Program
{
    [ImportingConstructor]
    public Program(IMessageSender messageSender) 
    {
    ...
    }
}

You can import fields, do optional import, import collections of services, including doing lazy importing with metadata so you can search for an appropriate service to instantiate. You can even re-import at runtime to look for new extensions.

share|improve this answer
    
While MEF is really cool for plugin stuff I don't think I'd like to use it as a general DI mechanism –  konrad Mar 30 '11 at 14:41
    
@MKO - Can you elaborate on what it's missing? I'm aware of all the articles where Glenn Block races to reassure people that MEF isn't out to replace all DI frameworks, but if you look at the details, it's obvious that's more of a political statement than anything else. However, if you can give a good list of features that MEF lacks compared with other DI frameworks, that will help people make an informed decision. Besides, the question is about DI frameworks in C#, and MEF is clearly a DI container in the .NET framework. –  Scott Whitlock Mar 30 '11 at 15:03
add comment

There are things that belong in languages, and things that don't. Long ago C recognized that IO did not belong in the language because it is external to the computing model and can be implemented with function libraries.

Dependency Injection is like that. It's external to language and can be implemented with appropriate frameworks.

One of the problems with modern languages is that they try to do too much. Eventually those languages collapse under their own weight as programmers flee to simpler languages.

share|improve this answer
    
I agree in theory, you can't have a language where every function is a feature of the language without it being bloated. However there's always room for new higher abstractions that helps us write better code. Perhaps dependency injection per se isn't the problem that needs solving but the problem it addresses, namely a way to make it easier for us to reduce dependencies. This might not be the best way to do it though :) –  konrad Apr 7 '11 at 13:41
add comment

It isn't needed

One of the things I like best about the best DI frameworks I've used is that the top-level configuration code is the only part of your code that needs to know about DI. Auto-wiring is done at the container and configuration/"module-loading" level, and your application code can be completely oblivious to it.

This means no attributes, no magic strings, no convention. Each piece of code only knows that it accepts code in its constructor (/properties/methods), and that's all.

With a design like that you don't need to alter the language at all to support Dependency Injection.

It is potentially dangerous

The thing I fear most about a language-integrated dependency injection system is that it would raise a barrier against any other implementation, yet it would probably paint itself into a corner in some aspect.

Some ways it could paint itself into a corner:

  • Only supporting XML-based configuration, or only code-based configuration
  • Not being able to cleanly support the Factory design pattern (not just transient components: run-time generated components)
  • Somehow changing my code so I was forced to use dependency injection, and couldn't simply instantiate my class for unit tests
  • Not supporting custom lifecycles
  • Not being extensible
  • Not being replaceable in cases where I need greater customization
  • Being broken in some way that we don't understand yet, because us .Net users haven't been using DI long enough to know the pitfalls
share|improve this answer
add comment
  1. You don't really describe the configuration mechanism, which IMHO is the tricky bit. How do you make all code running in one thread use DB-connection A, und all code in the other thread connection B? How do you block injection of a certain resource, because the user currently logged in is not allowed to access it?
  2. Don't use a global injector. Don't use any global thing at all, or you might as well use global variables. No, using OOP-speak such as singleton or "static" instead of global doesn't change their global nature.
  3. Consider a dynamically scoped container. While lexical scoping has rightfully won against dynamic scoping, I believe that dynamic scope would make a fine replacement for global scope. Differential inheritance would be a nice implementation (like in prototype-based inheritance).
  4. I believe that a language-mandated DI-mechanism should be really simple, none of that enterprisey stuff that is the norm in C# and Java. A dynamic scoping mechanism with a simple configuration layer on top might do the trick. Enterprisey solutions could be layered on top by third parties.
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.