Analyzing complex DI container registrations - ideas wanted

20 views
Skip to first unread message

Igal Tabachnik

unread,
May 5, 2012, 9:17:20 AM5/5/12
to altnet...@googlegroups.com
Hi everyone!

I am developing a plugin for ReSharper I wanted to do for a long while, called Agent Mulder. The idea is to analyze DI container registrations in your project, and help ReSharper fill the missing information about type usages.
I recorded a short demo, you're invited to watch it: https://vimeo.com/41113265 and let me know you think :)
I'm currently adding support to Castle Windsor, but eventually will add support to all major DI containers, pluggable via MEF.

For the most part, analyzing container registration is straightforward - I only have to detect enough information to know which concrete types are affected.
For example, Component.For<IFoo>().ImplementedBy<Foo>() is obvious, so is AllTypes.FromThisAssembly().BasedOn<IFoo>() - giving me just enough information to guestimate the concrete types that will be affected by this line.
The plugin utilizes ReSharper's Structural Search (SSR), to look for patterns in code, such as $component$.For<$type$>(), without having to manually reparse the files.

So while direct registrations are statically analyzable, some more complex things are not. Consider for example this registration:


container.Register(Classes
                .FromAssemblyInDirectory(new AssemblyFilter(".").FilterByName(an => an.Name.StartsWith("Ploeh.Samples.Booking")))
                .Where(t => !(t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dispatcher<>)))
                .WithServiceAllInterfaces());


Here the information depends on a predicate that will only be evaluated at runtime.
And now I need some help.

I have two ideas on how to try and analyze this registration, both are insane and difficult, and I hope you will have some other things I hadn't considered.
  1. Since all I have during my static analysis is ReSharper's AST of the source code (called PSI in ReSharper), I can try to to somehow parse the lambda expression AST into a LINQ expression tree which I can later compile to an actual delegate, then load the target assembly (determined by the FromAssembly*) manually, and apply the delegate to all the types in that assembly, getting the concrete type names OR
  2. Go nuts, and RUN the actual piece of code by compiling a small snippet, with references to the container assemblies with Mono, Roslyn, CodeDOM or whatever, then getting the actual registered components from the container.
Both options are have lots of cons to their pros - I really would like to stick to static analysis where possible. But if there is no other choice - I'd really like to choose the lesser of the two evils. I think the 2nd approach is easier to implement, but it might be both dangerous (executing user's code) and very performance-heavy.

Or I might not do this feature at all, I don't know :)

Anyway, sorry about the long writeup, I really need a brainstorming on this, and since I'm currently not in Israel, I can't really bug you about it in person during one of the ALT.NETs :)

Thanks in advance for your ideas!

-Igal


Ariel Raunstien

unread,
May 6, 2012, 6:48:14 PM5/6/12
to altnet...@googlegroups.com
While static analysis is available for non-compilable projects via re# - it's not there for runtime analysis. And the risks you've mentioned about reflecting on user code are indeed there.
But for static analysis (parsing the delegates and then locating the types) - you'd have to start chasing file references and build locations and project references and possible cyclic references and GACed assemblies and post-build actions (familiar with those?) and all sorts of what nots.

Maybe your solution should not be either of these. Maybe set up a "library" of dedicated Mulder rules (based on re# query syntax) for each container, which can handle all sorts of registrations oddities. If this plugin gains traction - more people will add custom rules to support their flavor of registration. If not - you've only written the specific rules you need.
Hell, if Mulder does well - people might conform their registration code with the preexisting templates...


Ariel Raunstien
+972-522-747408



--
You received this message because you are subscribed to the Google Groups "altnetisrael" group.
To post to this group, send email to altnet...@googlegroups.com.
To unsubscribe from this group, send email to altnetisrael...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/altnetisrael?hl=en.

Reply all
Reply to author
Forward
0 new messages