jab icon indicating copy to clipboard operation
jab copied to clipboard

Registration by convention

Open MattMinke opened this issue 3 years ago • 2 comments

I know at this point you are working through core features, stability and things of that nature. One thought / question that came up when looking at this project is will it be possible to support some kind of convention based registration ? With a traditional IoC container convention based registration comes with a time cost. scanning assemblies for types and doing type checks is expensive. This means application start takes longer. A compile time IoC can solve this issue if it supported such a feature.

Again. I know this is an advanced feature and there are other priorities at this point but wanted to plant the seed of what I think would be a game changing feature.

MattMinke avatar Apr 28 '21 19:04 MattMinke

I think it's a great idea. Which conventions do you think would be the most useful?

pakrym avatar Apr 28 '21 20:04 pakrym

So the ones I find myself using the most are

  • Implemented Interfaces - Each concrete type is registered to all interfaces it implements.
  • Matching Interface - Each concrete type is registered to an interfaces who's name matches the classes name (eg MyClass is registered to interface IMyClass)
  • As Self - Each concrete type is registered as its self.

So for example with Scrutor the convention registration ends up looking like this. In this particular case we are looking for all implementations of the interface ICoverageRule<> except CompositeCoverageRule<>.

services.Scan(scan => scan
                .FromApplicationDependencies()
                .AddClasses(cls => cls.Where(type =>
                type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICoverageRule<>))
                && !(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(CompositeCoverageRule<>))
                ))
                .AsImplementedInterfaces()
                .WithSingletonLifetime());

With Ninject the API surface for registering by convention adds a layer of abstraction over the type discovery and filtering. This abstraction while nice for the end developer I think is overkill. The simpler API of Scrutor I feel is more familiar to developers and does not require them to learn another API. Ninject adds more conventions but these are the ones I find myself using the most :

Base Type - Each concrete type is registered to the base type it inherits from. Default Interfaces - This rule is similar to Matching Interface but expands on it to allow the concrete type to be registered to more than one interface that matches the Matching Interface convention Single Interface - Each concrete type is registered to the one and only one interface it implements. All Interfaces - Each concrete type is registered to all interfaces it implements.

The other thing to consider when registering types by convention is what lifetime is going to be applied to each registration. I have registered types by convention with all lifetimes but Singleton and Transient lifetimes are the most common lifetime used with Convention based registration in my experience

MattMinke avatar Apr 28 '21 21:04 MattMinke