Compile-time / Post-Build Dependency Injection IoC?
Asked Answered
A

3

7

I currently use NInject to bind interfaces to concrete types and inject those into my classes. However, it is my understanding that this is a run-time affair. To me, it seems like a point of attack if someone wanted to change the behavior of my application.

Is there anything that would allow me to migrate my dependency injection IoC to compile time (Read: post-build IL weaving/replacement)?


To Elaborate

In my code I setup a binding

Bind<IFoo>().To<Foo>()
Bind<Bar>().ToSelf().InSingletonScope();

with ctor Foo(Bar dependency)

At the root of my application (on start-up) I resolve the graph

var foo = kernel.Get<IFoo>();

Assume I have no service locators (anti-pattern anyway right?). So I have no use for kernel anymore.

Now I want to have a "post-build release-compile" that replaces the kernel's resolution engine with instanciators, or references to constant/singleton, etc. Such that while my code looks like this;

var foo = kernel.Get<IFoo>();

In reality, after IL replacement in my final build stage, it looks like this:

var bar = new Bar(); 
var foo = new Foo(bar);

And there is no reference to NInject anymore.

My rational for this question is that I'm using Fody to IL Weave all my PropertyChanged raisers and I'm wondering whether it would be possible to do something similar for Dependency Injection.

Andrey answered 22/3, 2013 at 10:58 Comment(14)
Are the Ninject dependency registrations in xml or in code?Apostil
Could you please explain in more detail what is compile time injection?Marvelofperu
I presume your configuration for your DI is done in code via the modules. So you already get compile time safety even if the DI hookup happens during runtime. However that is going off on a tangent, if we look at the problem you are putting forward My DI happens at runtime but I want it to happen at compile time, why would you want to use Dependency Injection in the first place? you may as well just remove the modules and just manually assign instances or factories to implementations so there is no runtime point of attack. For me half the reason you use DI is to get runtime configurationCheyennecheyne
The whole point of IoC is to have it at run-time.Permeability
Can you explain what you mean by point of attack ? Are you referring to someone replacing one of your implementations with a rogue one, by replacing one of your DLLs ? If this is the issue, I recommend you look at Strong Name signing your DLLs.Stipend
@IlyaIvanov Well lets say I have IFoo and some Bar that wants IFoo in ctor. I setup the binding in code, compile, run. NInject kernel kicks off, I ask for Bar and it resolves the dependency. But I've compiled my binding definition. I'm compiling my intent already, but I have to wait until run-time for the resolving. I'm thinking, I don't see why I can't have a post-build stage that resolves dependencies and replaces with code that is IL Weaved in.Andrey
@MeirionHughes If this is for an efficiency/optimization, do you have an actual measurable impact from Ninject's DI? Is it currently a bottleneck that is negatively impacting user experience?Pickerel
I can't be sure.. this is a shot in the dark. You may be able to use something like PostSharp for this. postsharp.netStipend
@ChrisSinclair No its hypothetical. I've been using Fody to IL Weave my PropertyChanged raisers and I'm wondering whether something similar could be done for NInject.Andrey
What you're talking about is post compilation tools such as PostSharp. Problem with those tools is in fact that they do post compilation. This makes unit testing again as hard not using DI at all (one of the main reasons to do DI).Archon
@Archon Ahh... yes, good point. But what if I have something that replaces the IoC IL-code only on release (after testing)? Build-server->Test->OnPass->Replace NInject with IL-Weaved concrete code->ReleaseAndrey
@MeirionHughes: Would be possible in theory, but what's the point of doing that?Archon
If you wish to have compile time support because of performance reasons, you should take a look at Simple Injector. Its performance characteristics are similar to what you'll find when using code weaving tools such as PostSharp.Archon
One place where such thing would be great are big VSTO addons for Excel where container is used for all things. Container construction can take 100ms of 2000ms of addon start, hampering Excel user experience.Minard
B
4

As discussed, your cited reasons for doing this don't add up. However, Philip Laureano (Linfu author) did a Hiro project some time back which does pre-deployment DI. No idea if it went anywhere...

Bodnar answered 23/3, 2013 at 9:54 Comment(3)
On reflection this is the only answer thus far that answers the question, rather than my original rational for asking it. IoC in an of itself is a design concept, irrespective of whether the application of the inversion container is performed manually, at compile time, or at run-time. So I'm changing accepted answer to this. I would still love to see a fody-like IL weaver though. :PAndrey
@MeirionHughes Ha, what took you so long :D I see I upvoted the other answer as it is useful regardless of ho directly it answers it. The only logical next step based on your comment is of course for you do to a PR to Fody leveraging Hiro as a basis :PBodnar
well, I have been looking for a reason to make a fody addon. :PAndrey
A
8

From a security perspective in general, the use of a DI container does not pose any extra threats to your application.

When you write a service (such as web service or web site) application, the attacker could only change the DI configured behavior of the application when that application or server has already been compromized. When this happens, the server should be be considered lost (you will have to reformat that server or throw it away completely). DI doesn't make this worse, since a DI container does typically not allow the behavior to be changed from the outside. You will have to do something very weird to make this happen.

For an application that runs on the user's machine on the other hand, you should always consider that application to be compromised, since an attacker can decompile your code, change the behavior at runtime etc. Again, DI doesn't make this worse, since you can only protect yourself against attacks on the service boundary. That client app must communicate with the server and the place to store your valuable assets is within the service boundaries. For instance, you should never store a accounts password inside a DLL on the client. No matter whether it is encrypted or not.

The use of DI however, can make it somewhat easier for an attacker to change the behavior of a client application, especially when you configure everything in XML. But that holds for everything you store in the configuration file. And if that's your only line of defense (either with or without DI) you're screwed anyway.

it seems like a point of attack if someone wanted to change the behavior of my application

Please note that any application can be decompiled, changed, and recompiled. It doesn't matter whether it's managed (.NET, Java) or not (C++), or obfuscated or not. So again, from a security perspective it doesn't matter whether you do runtime DI or compile-time DI. If this is an issue, don't deploy that code on machines that you have no control over.

Archon answered 22/3, 2013 at 11:18 Comment(0)
B
4

As discussed, your cited reasons for doing this don't add up. However, Philip Laureano (Linfu author) did a Hiro project some time back which does pre-deployment DI. No idea if it went anywhere...

Bodnar answered 23/3, 2013 at 9:54 Comment(3)
On reflection this is the only answer thus far that answers the question, rather than my original rational for asking it. IoC in an of itself is a design concept, irrespective of whether the application of the inversion container is performed manually, at compile time, or at run-time. So I'm changing accepted answer to this. I would still love to see a fody-like IL weaver though. :PAndrey
@MeirionHughes Ha, what took you so long :D I see I upvoted the other answer as it is useful regardless of ho directly it answers it. The only logical next step based on your comment is of course for you do to a PR to Fody leveraging Hiro as a basis :PBodnar
well, I have been looking for a reason to make a fody addon. :PAndrey
G
3

I am working on a compile time IOC container for .Net utilizing source generators:

https://github.com/YairHalberstadt/stronginject

https://www.nuget.org/packages/StrongInject/

With it you can do the following:

using StrongInject;

[Registration(typeof(Foo), typeof(IFoo))]
[Registration(typeof(Bar), Scope.SingleInstance)]
public class Container : IContainer<IFoo> {}

public static class Program
{
    public static void Main()
    {
        new Container().Resolve(foo => //use foo here);
    }
}

This will give you compile time errors and warnings if it can't resolve IFoo and avoids use of reflection.

Glyceride answered 12/8, 2020 at 11:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.