Skip to content

Commit c8e7c91

Browse files
committed
Added comments and icon
1 parent 619a102 commit c8e7c91

5 files changed

Lines changed: 121 additions & 3 deletions

File tree

NetCore.AutoRegisterDi.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj",
99
EndProject
1010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{82D01612-D8DE-4C78-8394-19712BF8FCF5}"
1111
ProjectSection(SolutionItems) = preProject
12+
..\..\..\OneDrive - Selective Analytics Ltd\1 Business\1 TSF stuff\1 Standard Stationary\images\AutoRegisterDiIcon128.png = ..\..\..\OneDrive - Selective Analytics Ltd\1 Business\1 TSF stuff\1 Standard Stationary\images\AutoRegisterDiIcon128.png
1213
LICENCE.txt = LICENCE.txt
1314
READMe.md = READMe.md
1415
EndProjectSection

NetCore.AutoRegisterDi/AutoRegisterData.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,36 @@
77

88
namespace NetCore.AutoRegisterDi
99
{
10+
/// <summary>
11+
/// This holds the data passed between the various stages of the AutoRegisterDi extension methods
12+
/// </summary>
1013
public class AutoRegisterData
1114
{
15+
/// <summary>
16+
/// RegisterAssemblyPublicNonGenericClasses uses this to create the initial data
17+
/// </summary>
18+
/// <param name="services"></param>
19+
/// <param name="typesToConsider"></param>
1220
public AutoRegisterData(IServiceCollection services, IEnumerable<Type> typesToConsider)
1321
{
1422
Services = services ?? throw new ArgumentNullException(nameof(services));
1523
TypesToConsider = typesToConsider ?? throw new ArgumentNullException(nameof(typesToConsider));
1624
}
1725

26+
/// <summary>
27+
/// This carries the service register
28+
/// </summary>
1829
public IServiceCollection Services { get; }
1930

31+
/// <summary>
32+
/// This holds the class types found by the RegisterAssemblyPublicNonGenericClasses
33+
/// </summary>
2034
public IEnumerable<Type> TypesToConsider { get; }
35+
36+
/// <summary>
37+
/// This holds an options test method which will be applied using a Where clause to filter the classes
38+
/// If the TypeFiler is null, then no filtering is done
39+
/// </summary>
2140
public Func<Type, bool> TypeFilter { get; set; }
2241
}
2342
}

NetCore.AutoRegisterDi/AutoRegisterHelpers.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
namespace NetCore.AutoRegisterDi
1010
{
11+
/// <summary>
12+
/// This contains the extension methods for registering classes automatically
13+
/// </summary>
1114
public static class AutoRegisterHelpers
1215
{
1316
/// <summary>

NetCore.AutoRegisterDi/NetCore.AutoRegisterDi.csproj

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
5-
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
5+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
6+
<PackageVersion>1.0.0</PackageVersion>
7+
<Version>1.0.0</Version>
8+
<AssemblyVersion>1.0.0.0</AssemblyVersion>
9+
<FileVersion>1.0.0.0</FileVersion>
10+
<PackageProjectUrl>https://github.com/JonPSmith/NetCore.AutoRegisterDi</PackageProjectUrl>
11+
<PackageLicenseUrl>https://raw.githubusercontent.com/JonPSmith/NetCore.AutoRegisterDi/master/LICENCE.txt</PackageLicenseUrl>
12+
<RepositoryUrl>https://github.com/JonPSmith/NetCore.AutoRegisterDi</RepositoryUrl>
13+
<RepositoryType>Git</RepositoryType>
14+
<PackageTags>NetCore DependencyInjection di</PackageTags>
15+
<PackageReleaseNotes>First release</PackageReleaseNotes>
16+
<Authors>Jon P Smith</Authors>
17+
<Company>Selective Analytics</Company>
18+
<Description>Extension method to find/register classes in an assembly into Microsoft.Extensions.DependencyInjection</Description>
619
</PropertyGroup>
720

821
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
922
<DocumentationFile>bin\Debug\netstandard2.0\NetCore.AutoRegisterDi.xml</DocumentationFile>
1023
</PropertyGroup>
1124

25+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
26+
<DocumentationFile>bin\Release\netstandard2.0\NetCore.AutoRegisterDi.xml</DocumentationFile>
27+
</PropertyGroup>
28+
1229
<ItemGroup>
1330
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.0" />
1431
</ItemGroup>

READMe.md

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,81 @@
11
# NetCore.AutoRegisterDi
22

3-
This library contains
3+
This [NuGet library]()
4+
contains an extension method to scan an assemby and register all
5+
the public classes against their implemented interfaces(s) into the
6+
Microsoft.Extensions.DependencyInjection dependency injection provider.
7+
8+
I have written a simple version of AutoFac's `RegisterAssemblyTypes`
9+
method that works directly with Microsoft's DI provider.
10+
Here is an example of me using this with ASP.NET Core
11+
12+
```c#
13+
public void ConfigureServices(IServiceCollection services)
14+
{
15+
//... other configure code removed
16+
17+
var assemblyToScan = Assembly.GetExecutingAssembly(); //..or whatever assembly you need
18+
19+
service.RegisterAssemblyPublicNonGenericClasses(assemblyToScan)
20+
.Where(c => c.Name.EndsWith("Service"))
21+
.AsPublicImplementedInterfaces();
22+
```
23+
24+
## Wht have I written this extension?
25+
26+
There are two reasons:
27+
28+
1. I really hate having to hand-code each registering of the services - this
29+
extension method scans assembles and finds/registers classes with interfaces for you.
30+
2. I used to use [AutoFac's](https://autofac.org/) [assembly scanning](http://autofac.readthedocs.io/en/latest/register/scanning.html#assembly-scanning)
31+
feature, but I then saw a [tweet by @davidfowl](https://twitter.com/davidfowl/status/987866910946615296) about
32+
[Dependency Injection container benchmarks](https://ipjohnson.github.io/DotNet.DependencyInjectionBenchmarks/)
33+
which showed the Microsoft's DI provider was much faster than AutoFac.
34+
I therefore implemented a similar (but not exactly the same) feature for the
35+
Microsoft.Extensions.DependencyInjection library.
36+
37+
### Detailed information
38+
39+
There are three parts:
40+
1. `RegisterAssemblyPublicNonGenericClasses`, which finds all the classes.
41+
2. An options `Where` method, which allows you to filter the classes to be considered.
42+
3. The `AsPublicImplementedInterfaces` method which finds ant interfaces on a class and
43+
registers those interfaces as pointing to the class.
44+
45+
46+
#### 1. The `RegisterAssemblyPublicNonGenericClasses` method
47+
48+
The `RegisterAssemblyPublicNonGenericClasses` method will find all the classes
49+
in the assembly that I referenced that are considered useful for registering.
50+
The exact criteria I use are:
51+
52+
- Public access
53+
- Not nested, e.g. It won't look at classes defined inside other classes
54+
- Not Generic, e.g. MyClass<T>
55+
- Not Abstract
56+
57+
It can take a list/array of assemblies to scan. Two typical wasy of providing an assembly are:
58+
59+
- `Assembly.GetExecutingAssembly()`, which does what is says
60+
- `Assembly.GetAssembly(typeof(YourClass))`, which gets the assembly that `YourClass` was defined in.
61+
62+
#### 2. The `Where` method
63+
64+
Pretty straughtforward - you are provided with the `Type` of each class and
65+
you can filter by any of the `Type` properties etc. This allows you to
66+
do things like only registering certain classes,
67+
e.g `Where(c => c.Name.EndsWith("Service"))`
68+
69+
*NOTE: Useful also if you want to register some classes with a different timetime scope.*
70+
71+
#### 3. The `AsPublicImplementedInterfaces` method
72+
73+
The `AsPublicImplementedInterfaces` method finds any public, non-nested interfaces
74+
(apart from `IDisposable`) that each class implements and registers each
75+
interface, known as *service type*, against the class, known as the *implementation type*.
76+
77+
By default it will register the classes as having a lifetime of `ServiceLifetime.Transient`,
78+
but there is a parameter that allows you to override that.
79+
80+
*See this [useful article](https://joonasw.net/view/aspnet-core-di-deep-dive)
81+
on what lifetime (and other terms) means.*

0 commit comments

Comments
 (0)