Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Registration by convention #42

Open
MattMinke opened this issue Apr 28, 2021 · 2 comments
Open

Registration by convention #42

MattMinke opened this issue Apr 28, 2021 · 2 comments

Comments

@MattMinke
Copy link

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.

@pakrym
Copy link
Owner

pakrym commented Apr 28, 2021

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

@MattMinke
Copy link
Author

MattMinke commented Apr 28, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants