-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBootstrapper.cs
184 lines (150 loc) · 6.86 KB
/
Bootstrapper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
//===============================================================================
// TinyIoC.Bootstrapper
//
// A bootstrapper implementation the TinyIoC Inversion of Control container
//
// https://github.com/jonegerton/TinyIoC.Bootstrapper
//===============================================================================
// Copyright © Jon Egerton. All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace TinyIoC
{
/// <summary>
/// TinyIoC bootstrapper. Handles auto registration.
/// </summary>
public interface IBootstrapper
{
void ConfigureApplicationContainer(TinyIoCContainer container);
}
/// <summary>
/// Default TinyIoC bootstrapper. Handles auto registration to cover most cases.
/// </summary>
/// <remarks>
/// Inherit from this class to add additional Ignored Assemblies and Types, and to add custom registrations.
/// </remarks>
public class Bootstrapper : IBootstrapper
{
//Elements of this are based on code in Nancy here:
//https://github.com/NancyFx/Nancy/blob/6ceb54daec2dc230ab6fe55b367d3837e262c1db/src/Nancy/DefaultNancyBootstrapper.cs
/// <summary>
/// Default assemblies that are ignored for registration
/// </summary>
public static IEnumerable<Func<string, bool>> DefaultAutoRegisterIgnoredAssemblies = new Func<string, bool>[]
{
asm => asm.StartsWith("Microsoft.", StringComparison.InvariantCulture),
asm => asm.StartsWith("System.", StringComparison.InvariantCulture),
asm => asm.StartsWith("System,", StringComparison.InvariantCulture),
asm => asm.StartsWith("mscorlib,", StringComparison.InvariantCulture),
};
/// <summary>
/// Default types that are ignored for auto registration
/// </summary>
public static IEnumerable<Func<Type, bool>> DefaultAutoRegisterIgnoredTypes = new Func<Type, bool>[]
{
typ => typ.FullName.StartsWith("TinyIoC.", StringComparison.InvariantCulture),
};
/// <summary>
/// Default path to search for assemblies to index.
/// </summary>
public static string DefaultSearchPath
{
get {
return new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)).LocalPath;
}
}
/// <summary>
/// Gets the assemblies names to ignore when autoregistering the application container
/// Return true from the delegate to ignore that particular assembly, returning true
/// does not mean the assembly *will* be included, a false from another delegate will
/// take precedence.
/// </summary>
protected virtual IEnumerable<Func<string, bool>> AutoRegisterIgnoredAssemblies
{
get { return DefaultAutoRegisterIgnoredAssemblies; }
}
/// <summary>
/// Gets the types to ignore when autoregistering the application container
/// Return true from the delegate to ignore that particular type, returning true
/// does not mean the type *will* be included, a false from another delegate will
/// take precedence.
/// </summary>
protected virtual IEnumerable<Func<Type, bool>> AutoRegisterIgnoredTypes
{
get { return DefaultAutoRegisterIgnoredTypes; }
}
/// <summary>
/// Gets the path to search for assemblies to index.
/// </summary>
protected virtual string AutoRegisterSearchPath
{
get {return DefaultSearchPath;}
}
/// <summary>
/// Configures the container using AutoRegister
/// </summary>
/// <param name="container">Container instance</param>
public virtual void ConfigureApplicationContainer(TinyIoCContainer container)
{
AutoRegister(container, AutoRegisterIgnoredAssemblies, AutoRegisterIgnoredTypes);
}
/// <summary>
/// Extra assemblies to include in mapping that might not be easily discoverable
/// </summary>
public List<Assembly> AddedAssemblies { get; set; }
private IEnumerable<Assembly> LoadAssemblies(IEnumerable<Func<string, bool>> ignoredAssemblies)
{
List<Assembly> allAssemblies = new List<Assembly>();
//Get assemblies in the AppDomain
allAssemblies.AddRange(System.AppDomain.CurrentDomain.GetAssemblies());
//Get list of files
var files = Directory.GetFiles(AutoRegisterSearchPath, "*.dll");
//A function to normalize file paths
Func<string, string> normalizePath = s => new Uri(s).LocalPath.ToLowerInvariant();
//Filter files list (so we don't load things we don't require)
files = files.Where(f => !ignoredAssemblies.Any(ia => ia(Path.GetFileName(f)))).ToArray();
//Add files found (if we haven't already got them)
foreach (string dll in files)
{
var dllPath = normalizePath(dll);
if (allAssemblies.All(a => normalizePath(a.Location) != dllPath))
allAssemblies.Add(Assembly.LoadFile(dll));
}
//Include the added assemblies
if (AddedAssemblies != null)
{
foreach (var asm in AddedAssemblies)
{
var asmPath = normalizePath(asm.Location);
if (allAssemblies.All(a => normalizePath(a.Location) != asmPath))
allAssemblies.Add(Assembly.LoadFile(asm.Location));
}
}
//Apply filters again across full set of assemblies
var assemblies = allAssemblies.Where(a => !ignoredAssemblies.Any(ia => ia(a.FullName))).ToList();
return assemblies;
}
/// <summary>
/// Executes auto registation with the given container.
/// </summary>
/// <param name="container">Container instance</param>
private void AutoRegister(TinyIoCContainer container, IEnumerable<Func<string, bool>> ignoredAssemblies, IEnumerable<Func<Type, bool>> ignoredTypes)
{
container.AutoRegister(LoadAssemblies(ignoredAssemblies),
DuplicateImplementationActions.RegisterMultiple,
t => !ignoredTypes.Any(it => it(t)));
}
}
}