Skip to content

Commit 55ae61b

Browse files
committed
Improved docs
1 parent 4004b1d commit 55ae61b

File tree

3 files changed

+68
-101
lines changed

3 files changed

+68
-101
lines changed

NetCore.AutoRegisterDi.sln

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 15
4-
VisualStudioVersion = 15.0.27703.2026
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.8.34322.80
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCore.AutoRegisterDi", "NetCore.AutoRegisterDi\NetCore.AutoRegisterDi.csproj", "{FC8E0DD3-616E-4B90-9342-754E08593D4C}"
77
EndProject
@@ -11,11 +11,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1111
ProjectSection(SolutionItems) = preProject
1212
LICENCE.txt = LICENCE.txt
1313
READMe.md = READMe.md
14+
ReleaseNotes.md = ReleaseNotes.md
1415
EndProjectSection
1516
EndProject
16-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestAssembly", "TestAssembly\TestAssembly.csproj", "{2B4E7847-FFF8-472A-987D-6808B1DCE56F}"
17+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestAssembly", "TestAssembly\TestAssembly.csproj", "{2B4E7847-FFF8-472A-987D-6808B1DCE56F}"
1718
EndProject
18-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestBadAssembly", "TestBadAssembly\TestBadAssembly.csproj", "{0E090B35-D105-49C1-95BE-EDC2655D6399}"
19+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestBadAssembly", "TestBadAssembly\TestBadAssembly.csproj", "{0E090B35-D105-49C1-95BE-EDC2655D6399}"
1920
EndProject
2021
Global
2122
GlobalSection(SolutionConfigurationPlatforms) = preSolution

READMe.md

Lines changed: 43 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,40 @@
11
# NetCore.AutoRegisterDi
22

3-
This [NuGet library](https://www.nuget.org/packages/NetCore.AutoRegisterDi/) contains an extension method to scan an assemby and register all the non-generic public classes (see [excluded class types](https://github.com/JonPSmith/NetCore.AutoRegisterDi#1-the-registerassemblypublicnongenericclasses-method)) against their implemented interfaces(s) into the `Microsoft.Extensions.DependencyInjection` dependency injection provider.
3+
I have written a simple version of AutoFac's `RegisterAssemblyTypes` method that works directly with Microsoft's DI provider, i.e this library to scan an assemby (or assemblies) on your application and register all the public normal classes (i.e not [generic classes](https://www.tutorialspoint.com/Generics-vs-non-generics-in-Chash)) that have an interface into the Microsoft NET's [Dependency injection provider]https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection (DI for short).
44

5-
**Version 2.0.0 update**: New attributes for defining the `ServiceLifetime` of your classes, e.g. adding the `[RegisterAsScoped]` attribute to a class will mean its `ServiceLifetime` in the DI will be set to `Scoped`. *Added by Fedor Zhekov (GitHub @ZFi88)*.
5+
The NetCore.AutoRegisterDi is available on [NuGet as EfCore.SchemaCompare](https://www.nuget.org/packages/NetCore.AutoRegisterDi) and is an open-source library under the MIT license. See [ReleaseNotes](https://github.com/JonPSmith/NetCore.AutoRegisterDi/blob/masterReleaseNotes.md) for details of changes and information for each release.
66

7-
**Version 2.1.0 update**: Added ability ignore an interface, plus added `ISerializable` interface to list of ignored interfaces and outputs results so that you can check it is registering the correct things.
7+
## Why have I written this extension?
88

9-
I have written a simple version of AutoFac's `RegisterAssemblyTypes` method that works directly with Microsoft's DI provider. Here are an example of me using this with ASP.NET Core.
9+
There are two reasons:
10+
11+
1. I really hate having to hand-code each registering of my services - this extension method scans assembles and finds/registers classes with interfaces for you.
12+
2. I used to use [AutoFac's](https://autofac.org/) [assembly scanning](http://autofac.readthedocs.io/en/latest/register/scanning.html#assembly-scanning)
13+
feature, but I then saw a [tweet by @davidfowl](https://twitter.com/davidfowl/status/987866910946615296) about [Dependency Injection container benchmark (https://ipjohnson.github.io/DotNet.DependencyInjectionBenchmarks/) which showed the Microsoft's DI provider was much faster than AutoFac. I therefore implemented a similar (but not exactly the same) feature for the Microsoft.Extensions.DependencyInjection library.
14+
15+
## Documentation
16+
17+
_NOTE: There is an [article about this library](https://www.thereformedprogrammer.net/asp-net-core-fast-and-automatic-dependency-injection-setup/) which gives you an overview of this library. Useful if you haven't used this library before._
1018

11-
## Example 1 - scan the calling assembly
19+
### Two, simple examples
20+
21+
#### Example 1 - scan the calling assembly
22+
23+
This example scans the assembly where you call the AutoRegisterDi's `RegisterAssemblyPublicNonGenericClasses` method for all the classes which has one or more public interfaces and the Class's name ends with "Service" are registered with .NET's
1224

1325
```c#
1426
public void ConfigureServices(IServiceCollection services)
1527
{
1628
//... other configure code removed
1729
18-
services.RegisterAssemblyPublicNonGenericClasses()
19-
.Where(c => c.Name.EndsWith("Service")) //optional
20-
.IgnoreThisInterface<IMyInterface>() //optional
30+
service.RegisterAssemblyPublicNonGenericClasses()
31+
.Where(c => c.Name.EndsWith("Service"))
2132
.AsPublicImplementedInterfaces();
2233
```
2334

24-
## Example 2 - scanning multiple assemblies
35+
#### Example 2 - scanning multiple assemblies
36+
37+
This example scans the three assemblies and registers *all* the classes that have one or more public interfaces. That's because I have commented out the `.Where(c => c.Name.EndsWith("Service"))` method.
2538

2639
```c#
2740
public void ConfigureServices(IServiceCollection services)
@@ -35,47 +48,28 @@ public void ConfigureServices(IServiceCollection services)
3548
Assembly.GetAssembly(typeof(MyServiceInAssembly2))
3649
};
3750

38-
services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan)
39-
.Where(c => c.Name.EndsWith("Service")) //optional
40-
.IgnoreThisInterface<IMyInterface>() //optional
51+
service.RegisterAssemblyPublicNonGenericClasses(assembliesToScan)
52+
//commenting the line below means it will scan all public classes
53+
//.Where(c => c.Name.EndsWith("Service"))
4154
.AsPublicImplementedInterfaces();
4255
```
4356

44-
Licence: MIT.
57+
### Detailed information
4558

46-
**See [this article](https://www.thereformedprogrammer.net/asp-net-core-fast-and-automatic-dependency-injection-setup/)
47-
for a bigger coverage of Microsoft DI and the use of this library in real applications.**
59+
There are four parts:
4860

49-
## Why have I written this extension
50-
51-
There are two reasons:
52-
53-
1. I really hate having to hand-code each registering of the services - this
54-
extension method scans assembles and finds/registers classes with interfaces for you.
55-
2. I used to use [AutoFac's](https://autofac.org/) [assembly scanning](http://autofac.readthedocs.io/en/latest/register/scanning.html#assembly-scanning)
56-
feature, but I then saw a [tweet by @davidfowl](https://twitter.com/davidfowl/status/987866910946615296) about
57-
[Dependency Injection container benchmarks](https://ipjohnson.github.io/DotNet.DependencyInjectionBenchmarks/)
58-
which showed the Microsoft's DI provider was much faster than AutoFac.
59-
I therefore implemented a similar (but not exactly the same) feature for the
60-
Microsoft.Extensions.DependencyInjection library.
61-
62-
## Detailed information
63-
64-
There are five parts:
65-
1. `RegisterAssemblyPublicNonGenericClasses`, which finds all the public classes that :
61+
1. `RegisterAssemblyPublicNonGenericClasses`, which finds all the public classes that:
6662
- Aren't abstract
6763
- Aren't a generic type, e.g. MyClass\<AnotherClass\>
6864
- Isn't nested. e.g. It won't look at classes defined inside other classes
69-
2. An `Where` extension method, which allows you to filter the classes to be considered.
70-
3. An `IgnoreThisInterface<IMyInterface>` extension method that allows you to add an interface to be ignored. This allows you to stop a class being registered
71-
4. The `AsPublicImplementedInterfaces` method which finds ant interfaces on a class and registers those interfaces as pointing to the class. It also returns a list of results that allows you check what classes have been registered with the DI provider.
72-
5. Various attributes that you can add to your classes to tell `NetCore.AutoRegisterDi` what to do:
65+
2. An optional `Where` method, which allows you to filter the classes to be considered.
66+
3. The `AsPublicImplementedInterfaces` method which finds ant interfaces on a class and registers those interfaces as pointing to the class.
67+
4. Various attributes that you can add to your classes to tell `NetCore.AutoRegisterDi` what to do:
7368
i) Set the `ServiceLifetime` of your class, e.g. `[RegisterAsSingleton]` to apply a `Singleton` lifetime to your class.
7469
ii) A `[DoNotAutoRegister]` attribute to stop library your class from being registered with the DI.
7570

76-
The following sections describes each part in detail.
7771

78-
### 1. The `RegisterAssemblyPublicNonGenericClasses` method
72+
#### 1. The `RegisterAssemblyPublicNonGenericClasses` method
7973

8074
The `RegisterAssemblyPublicNonGenericClasses` method will find all the classes in
8175

@@ -89,79 +83,31 @@ I only consider classes which match ALL of the criteria below:
8983
- Not Generic, e.g. MyClass\<T\>
9084
- Not Abstract
9185

92-
### 2. The `Where` method
86+
#### 2. The `Where` method
9387

9488
Pretty straightforward - you are provided with the `Type` of each class and you can filter by any of the `Type` properties etc. This allows you to do things like only registering certain classes, e.g `Where(c => c.Name.EndsWith("Service"))`
9589

96-
*NOTES:*
97-
98-
- Useful also if you want to register some classes with a different lifetime scope: See section 4.
99-
- You can use multiple `Where` methods. They have an `&&` effect, e.g. the following code would register all the classes other than `Class1` and `Class2`:
100-
101-
```c#
102-
service.RegisterAssemblyPublicNonGenericClasses()
103-
.Where(c => c.Name != "Class1"))
104-
.Where(c => c.Name != "Class2"))
105-
.AsPublicImplementedInterfaces();
106-
```
107-
108-
### 3. The `IgnoreThisInterface<IMyInterface>` method
90+
*NOTE: Useful also if you want to register some classes with a different time scope - See next section.*
10991

110-
There are some interfaces that you don't want your classes to be registered, for instance `IDisposable` and `ISerializable` and these are already registered in NetCore.AutoRegisterDi. This means that no class will be registered against these two interfaces.
111-
112-
You can add extra interfaces to the interface ignore list using the `IgnoreThisInterface<IMyInterface>`, e.g. the following code would add the two interfaces `IMyInterface1` and `IMyInterface2` to the interface ignore list.
113-
114-
```c#
115-
service.RegisterAssemblyPublicNonGenericClasses()
116-
.IgnoreThisInterface<IMyInterface1>()
117-
.IgnoreThisInterface<IMyInterface2>()
118-
.AsPublicImplementedInterfaces();
119-
```
120-
121-
### 4. The `AsPublicImplementedInterfaces` method
92+
#### 3. The `AsPublicImplementedInterfaces` method
12293

12394
The `AsPublicImplementedInterfaces` method finds any public, non-nested interfaces
124-
(apart from the interfaces in the interface ignore list) that each class implements and registers each interface, known as *service type*, against the class, known as the *implementation type*. This means if you use an interface in a constructor (or other DI-enabled places) then the Microsoft DI resolver will provide an instance of the class that interface
95+
(apart from `IDisposable`) that each class implements and registers each
96+
interface, known as *service type*, against the class, known as the *implementation type*.
97+
This means if you use an interface in a constructor (or other DI-enabled places)
98+
then the Microsoft DI resolver will provide an instance of the class that interface
12599
was linked to.
126-
127100
*See [Microsoft DI Docs](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1) for more on this*.*
128101
129-
#### 4a. Debugging what classes/interfaces have been registered
130-
131-
The `AsPublicImplementedInterfaces` method returns a list of `AutoRegisteredResult` classes, which shows what classes have been registered with the DI provider. By catching this result you can quickly see what the NetCore.AutoRegisterDi library has registered.
132-
133-
The following code would capture the list of results
134-
135-
```c#
136-
var results = service.RegisterAssemblyPublicNonGenericClasses()
137-
.IgnoreThisInterface<IMyInterface>()
138-
.AsPublicImplementedInterfaces();
139-
```
140-
141-
If you hover of the `results` list it will show a list similar to the one below, but with you own classes/interfaces.
142-
143-
```text
144-
The interface IDisposable is ignored
145-
The interface ISerializable is ignored
146-
The interface IMyInterface is ignored
147-
LocalScopeService : ILocalService (Scoped)
148-
LocalService : ILocalService (Transient)
149-
LocalService : IAnotherInterface (Transient)
150-
```
151-
152-
##### 4b. Changing the default ServiceLifetime
153-
154-
The default lifetime of registered class is `ServiceLifetime.Transient`, there are two ways to change this.
155-
156-
- Add a NetCore.AutoRegisterDi lifetime attribute to your class (see section 5).
157-
- You can provide a `ServiceLifetime` to the `AsPublicImplementedInterfaces` method, e.g. `AsPublicImplementedInterfaces(ServiceLifetime.Scoped)`, which will change the default lifetime to the parameter value you provide.
102+
By default it will register the classes as having a lifetime of `ServiceLifetime.Transient`,
103+
but there is a parameter that allows you to override that.
158104

159105
*See this [useful article](https://joonasw.net/view/aspnet-core-di-deep-dive)
160106
on what lifetime (and other terms) means.*
161107

162-
### 5. The attributes
108+
#### 4. The attributes
163109

164-
Fedor Zhekov, (GitHub @ZFi88) added attributes to allow you to define the `ServiceLifetime` of your class, and also exclude your class from being registered with the DI.
110+
Fedor Zhekov, (GitHub @ZFi88) added attributes to allow you to define the `ServiceLifetime` of your class, and also exclude your class from being registered with the DI.
165111

166112
Here are the attributes that sets the `ServiceLifetime` to be used when `NetCore.AutoRegisterDi` registers your class with the DI.
167113

ReleaseNotes.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Release notes
2+
3+
## 2.1.0
4+
5+
- New feature: IgnoreThisInterface method adds a interface to its interface ignore list.
6+
- Improvement: Added ISerializable interface to the default interface ignore list (IDisposable is already in base ignore list)
7+
- Improvement: You can use muliple have Where methods to filter out classes
8+
- Improvement: Returns a list of the classes/interfaces registered with the DI provider (useful for debugging)
9+
10+
## 2.0.0
11+
12+
- New Feature: You can now set what ServiceLifetime your class has via Attributes. *Added by Fedor Zhekov (GitHub @ZFi88)*.
13+
14+
## 1.1.0
15+
16+
- New Feature: if no assembly is provided it scans the assembly that called the method.
17+
18+
## 1.0.0
19+
20+
- First release

0 commit comments

Comments
 (0)