Register a type without creating a concrete instance

May 5, 2009 at 6:51 PM
I am playing in the Funq test project to see if it is suitable for the kind of stuff we do in our app. I cannot find an easy way to register services without explicitly instantiating the concrete type and using/choosing a constructor. Our app stores the fully-qualified name of service providers in the database. In StructureMap, we would register an instance with "container.ForRequestedType(typeof(IService)).TheDefaultIsConcreteType(new Type(fullyQualifiedAssemblyName))" where fullyQualifiedAssemblyName is just a string. I cannot find an easy way to do this with Funq. Am I missing something?
May 5, 2009 at 7:02 PM
I guess the other feature I am looking for is the auto-wiring of dependencies for the IService in the previous snippet. If you have to explicitly choose a constructor and wire-up its parameters, does that mean auto-wiring is not present? Is it on the list?
Coordinator
May 5, 2009 at 7:49 PM
There is no auto-wiring, for performance reasons.
You could code-gen the calls to the typed Register methods from the database, using T4, at design-time.
May 5, 2009 at 9:31 PM
What about my first question: can you register a type from a Type object rather than using an instance or a factory? What I'm trying to get out of this is being able to register a type in an assembly that was not referenced when the registration code was compiled, such as a plugin.
Coordinator
May 6, 2009 at 8:56 PM
Again, that kind of registration would have a performance impact because we'd have to discover the constructor via reflection.
The intended usage is that the project/assembly that provides the plugins, exposes a type that implements IFunqlet, which is then instantiated via reflection by the app/host which passes-in the Container to configure by the plugin. At that point, the plugin/funqlet knows its own types and can provide strong-typed factories for them.
May 7, 2009 at 12:28 PM
IFunqlet sounds interesting. Can you point to an example of the intended usage?
Coordinator
May 7, 2009 at 1:06 PM
Grab the latest drop of the Mobile Application Blocks from mobile.codeplex.com, which includes a .NET CF version of Funq, and see the samples included with its ContainerModel (which is the same codebase as Funq). There's an example showing modularity via IContainerModule (which is the same as IFunqlet

Let me know if that helps!
Oct 27, 2009 at 8:59 PM

Hi great, project by the way really like the way TDD is giving the libraries you create really nice API's, your screencasts and quality of your api's is making me give TDD a second look.

I still think you should provide a default auto-wiring implementation where you can AutoRegister based on type alone which just selects the most appropriate constructor (e.g. the largest one) and basically keeps a cache of a compiled delegate (using either Expression/Reflection.Emit) which just provides an implementation that cirles through each contstructor arg and populate it with container.Resolve<argtype>() and each public property and populate it with container.TryResolve<PropertyType>().

Feb 10, 2010 at 4:14 PM

Hey kzu,

Just want to say thanks for developing a really simple, clean IOC. Everything else looks over architected and it looks like you've brought the best features without the perf bloat.
I ended up replacing my existing IOC (for my opensource webservice framework) with Funq, and it's resulted in a perf boost and a cleaner and easier to use API - so thanks again.

Also I'm not sure if you've done it already (haven't seen it) but I've developed a generics/expression based AutoWire wrapper around your generic interfaces here:

http://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Common/ServiceStack.ServiceHost/ExpressionTypeFunqContainer.cs

It's built with the same spirit as Funq where all the perf cost happens during the 'registration phase'. Basically when you register a 'runtime type' it goes through and 'binds' the Funq resolver to the largest constructor and all its public properties (which I believe is the convention).

It exposes the following API's which allow you to register 'runtime types':

public void RegisterTypes(params Type[] serviceTypes)

public void RegisterTypes(params Type[] serviceTypes)
void RegisterTypes(IEnumerable<Type> serviceTypes)

Hope someone finds it Useful.

 

 

Coordinator
Feb 10, 2010 at 8:47 PM

This is interesting mythz. 

I think the killer approach though would be to have a way to generate the strong-typed registrations at compile-time. Someone looked at ccisamples CciSharp at ccisamples.codeplex.com/wikipage?title=CciSharp?

Feb 10, 2010 at 11:46 PM

Yeah it definitely looks like it would that approach would yield the best performance. Though would come at a cost of additional complexity of a post-build step and having to add an attribute and a dependency on every type you want to register. You can effectively achieve the same result with Code-Dom or T4 but I've recently been shying away from generated code if I can help it as it adds extra maintenance of managing the generated code-base, longer compile times, adding the post build step to visual studio + build agents, keeping everyone's sources in sync, debugging un-friendly ugly generated code, etc. Although this does look like it would solve some of the problems as it is a more seamless approach by mutating your code-output instead of generating added sources on the side. Being a compile-time process, I am curious about what the expected generated/mutated code would look like and how you would register it with a particular container instance? a static constructor for each type registering with a singleton container instance?

Well it will definitely improve the start-up perf -  important for mobile apps (not so much for web apps) although I don't think that it would yield a significant runtime benefit to justify the additional complexity.

I guess it all depends how you can integrate it into Funq, if you can wrap it up into an intuitive, non-invasive API and still provide the ability to re-configure the container at runtime than it may be the way to go.