Introduce IExtensionFactory as mechanism to create extensions
Rob Mensching committed
Nov 11, 2017 at 12:41 UTC
b6bf1604c32259757f75b4c35444cfe4ecc21a86
8 files changed
+75
-44
src/WixToolset.BuildTasks/DoIt.cs
+1
-1
@@ -181,7 +181,7 @@ namespace WixToolset.BuildTasks
181
{
182
var extensionManager = serviceProvider.GetService<IExtensionManager>();
183
184
- foreach (var type in new[] { typeof(WixToolset.Core.Burn.StandardBackend), typeof(WixToolset.Core.WindowsInstaller.StandardBackend) })
184
+ foreach (var type in new[] { typeof(WixToolset.Core.Burn.WixToolsetStandardBackend), typeof(WixToolset.Core.WindowsInstaller.WixToolsetStandardBackend) })
185
{
186
extensionManager.Add(type.Assembly);
187
}
src/WixToolset.Core.Burn/BurnBackendFactory.cs
renamed
+1
-1
@@ -7,7 +7,7 @@ namespace WixToolset.Core.Burn
7
using WixToolset.Extensibility;
8
using WixToolset.Extensibility.Services;
9
10
- internal class BackendFactory : IBackendFactory
10
+ internal class BurnBackendFactory : IBackendFactory
11
{
12
public bool TryCreateBackend(string outputType, string outputFile, IBindContext context, out IBackend backend)
13
{
src/WixToolset.Core.Burn/BurnExtensionFactory.cs
new
+22
@@ -0,0 +1,22 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core.Burn
4
+{
5
+ using System;
6
+ using WixToolset.Extensibility;
7
+
8
+ internal class BurnExtensionFactory : IExtensionFactory
9
+ {
10
+ public bool TryCreateExtension(Type extensionType, out object extension)
11
+ {
12
+ extension = null;
13
+
14
+ if (extensionType == typeof(IBackendFactory))
15
+ {
16
+ extension = new BurnBackendFactory();
17
+ }
18
+
19
+ return extension != null;
20
+ }
21
+ }
22
+}
src/WixToolset.Core.Burn/WixToolsetStandardBackend.cs
renamed
+1
-1
@@ -6,7 +6,7 @@ namespace WixToolset.Core.Burn
6
/// Denotes this assembly contains a backend that is considered
7
/// a standard part of the WiX Toolset.
8
/// </summary>
9
- public static class StandardBackend
9
+ public static class WixToolsetStandardBackend
10
{
11
}
12
}
src/WixToolset.Core.WindowsInstaller/WindowsInstallerExtensionFactory.cs
new
+22
@@ -0,0 +1,22 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core.WindowsInstaller
4
+{
5
+ using System;
6
+ using WixToolset.Extensibility;
7
+
8
+ internal class WindowsInstallerExtensionFactory : IExtensionFactory
9
+ {
10
+ public bool TryCreateExtension(Type extensionType, out object extension)
11
+ {
12
+ extension = null;
13
+
14
+ if (extensionType == typeof(IBackendFactory))
15
+ {
16
+ extension = new WindowsInstallerBackendFactory();
17
+ }
18
+
19
+ return extension != null;
20
+ }
21
+ }
22
+}
src/WixToolset.Core.WindowsInstaller/WixToolsetStandardBackend.cs
renamed
+1
-1
@@ -6,7 +6,7 @@ namespace WixToolset.Core.WindowsInstaller
6
/// Denotes this assembly contains a backend that is considered
7
/// a standard part of the WiX Toolset.
8
/// </summary>
9
- public static class StandardBackend
9
+ public static class WixToolsetStandardBackend
10
{
11
}
12
}
src/WixToolset.Core/ExtensionManager.cs
+26
-39
@@ -8,53 +8,36 @@ namespace WixToolset.Core
8
using System.Linq;
9
using System.Reflection;
10
using WixToolset.Data;
11
+ using WixToolset.Extensibility;
12
using WixToolset.Extensibility.Services;
13
13
- public class ExtensionManager : IExtensionManager
14
+ internal class ExtensionManager : IExtensionManager
15
{
15
- private List<Assembly> extensionAssemblies = new List<Assembly>();
16
+ private List<IExtensionFactory> extensionFactories = new List<IExtensionFactory>();
17
17
- /// <summary>
18
- /// Adds an assembly.
19
- /// </summary>
20
- /// <param name="assembly">Assembly to add to the extension manager.</param>
21
- /// <returns>The assembly added.</returns>
22
- public Assembly Add(Assembly assembly)
18
+ public void Add(Assembly extensionAssembly)
19
{
24
- this.extensionAssemblies.Add(assembly);
25
- return assembly;
20
+ var types = extensionAssembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && typeof(IExtensionFactory).IsAssignableFrom(t));
21
+ var factories = types.Select(t => (IExtensionFactory)Activator.CreateInstance(t)).ToList();
22
+
23
+ this.extensionFactories.AddRange(factories);
24
}
25
28
- /// <summary>
29
- /// Loads an assembly from a type description string.
30
- /// </summary>
31
- /// <param name="extension">The assembly type description string.</param>
32
- /// <returns>The loaded assembly. This assembly can be ignored since the extension manager maintains the list of loaded assemblies internally.</returns>
33
- /// <remarks>
34
- /// <paramref name="extension"/> can be in several different forms:
35
- /// <list type="number">
36
- /// <item><term>AssemblyName (MyAssembly, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089)</term></item>
37
- /// <item><term>Absolute path to an assembly (C:\MyExtensions\ExtensionAssembly.dll)</term></item>
38
- /// <item><term>Filename of an assembly in the application directory (ExtensionAssembly.dll)</term></item>
39
- /// <item><term>Relative path to an assembly (..\..\MyExtensions\ExtensionAssembly.dll)</term></item>
40
- /// </list>
41
- /// </remarks>
42
- public Assembly Load(string extension)
26
+ public void Load(string extensionPath)
27
{
44
- string assemblyName = extension;
28
Assembly assembly;
29
30
// Absolute path to an assembly which means only "load from" will work even though we'd prefer to
31
// use Assembly.Load (see the documentation for Assembly.LoadFrom why).
49
- if (Path.IsPathRooted(assemblyName))
32
+ if (Path.IsPathRooted(extensionPath))
33
{
51
- assembly = ExtensionManager.ExtensionLoadFrom(assemblyName);
34
+ assembly = ExtensionManager.ExtensionLoadFrom(extensionPath);
35
}
53
- else if (ExtensionManager.TryExtensionLoad(assemblyName, out assembly))
36
+ else if (ExtensionManager.TryExtensionLoad(extensionPath, out assembly))
37
{
38
// Loaded the assembly by name from the probing path.
39
}
57
- else if (ExtensionManager.TryExtensionLoad(Path.GetFileNameWithoutExtension(assemblyName), out assembly))
40
+ else if (ExtensionManager.TryExtensionLoad(Path.GetFileNameWithoutExtension(extensionPath), out assembly))
41
{
42
// Loaded the assembly by filename alone along the probing path.
43
}
@@ -65,21 +48,25 @@ namespace WixToolset.Core
48
// path, so we should try Assembly.LoadFrom one last time. We could have detected a directory
49
// separator character and used Assembly.LoadFrom directly, but dealing with path canonicalization
50
// issues is something we don't want to deal with if we don't have to.
68
- assembly = ExtensionManager.ExtensionLoadFrom(assemblyName);
51
+ assembly = ExtensionManager.ExtensionLoadFrom(extensionPath);
52
}
53
71
- return this.Add(assembly);
54
+ this.Add(assembly);
55
}
56
74
- /// <summary>
75
- /// Creates extension of specified type from assemblies loaded into the extension manager.
76
- /// </summary>
77
- /// <typeparam name="T">Type of extension to create.</typeparam>
78
- /// <returns>Extensions created of the specified type.</returns>
57
public IEnumerable<T> Create<T>() where T : class
58
{
81
- var types = this.extensionAssemblies.SelectMany(a => a.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && typeof(T).IsAssignableFrom(t)));
82
- return types.Select(t => (T)Activator.CreateInstance(t)).ToList();
59
+ var extensions = new List<T>();
60
+
61
+ foreach (var factory in this.extensionFactories)
62
+ {
63
+ if (factory.TryCreateExtension(typeof(T), out var obj) && obj is T extension)
64
+ {
65
+ extensions.Add(extension);
66
+ }
67
+ }
68
+
69
+ return extensions;
70
}
71
72
private static Assembly ExtensionLoadFrom(string assemblyName)
src/wix/Program.cs
+1
-1
@@ -49,7 +49,7 @@ namespace WixToolset.Core
49
{
50
var extensionManager = serviceProvider.GetService<IExtensionManager>();
51
52
- foreach (var type in new[] { typeof(WixToolset.Core.Burn.StandardBackend), typeof(WixToolset.Core.WindowsInstaller.StandardBackend) })
52
+ foreach (var type in new[] { typeof(WixToolset.Core.Burn.WixToolsetStandardBackend), typeof(WixToolset.Core.WindowsInstaller.WixToolsetStandardBackend) })
53
{
54
extensionManager.Add(type.Assembly);
55
}