-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathProviderFactory.cs
More file actions
62 lines (54 loc) · 2.46 KB
/
ProviderFactory.cs
File metadata and controls
62 lines (54 loc) · 2.46 KB
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
using System.Collections.Generic;
using System.Linq;
using Sandbox;
using Sandmod.Core.Logger;
namespace Sandmod.Core.Provider;
/// <summary>
/// Factory used for creating instances for auto-injection.
/// </summary>
public static class ProviderFactory
{
/// <summary>
/// Creates instances of the provided type <b><typeparamref name="T"/></b> based on the <see cref="ProviderAttribute"/> and <see cref="DefaultProviderAttribute"/>.
/// </summary>
/// <typeparam name="T">The type to provide</typeparam>
/// <returns>the created instances</returns>
public static IReadOnlyList<T> Provide<T>() where T : class
{
var typeName = typeof(T).Name;
var log = new SandmodLogger($"Provider/{typeof(T).Name}");
log.Info($"Providing instances for {typeName} ...");
var types = TypeLibrary.GetTypes<T>().ToList();
// Check for none default provides
var provideTypes = types.Where(type => type.HasAttribute<ProviderAttribute>()).ToList();
if (provideTypes.Any())
{
log.Info($"Providing {provideTypes.Count} instance(s)");
return provideTypes.Select(type => TypeLibrary.Create<T>(type.TargetType)).ToList();
}
types = types.Except(provideTypes).ToList();
// Check for default provides
var defaultTypes = types
.Select(type => new KeyValuePair<TypeDescription, DefaultProviderAttribute>(type,
TypeLibrary.GetAttribute<DefaultProviderAttribute>(type.TargetType)))
.Where(pair => pair.Value != null)
.GroupBy(pair => pair.Value.Priority)
.OrderByDescending(group => group.Key)
.ToList();
if (defaultTypes.Any())
{
var defaultPriority = defaultTypes.First();
if (defaultPriority.Count() > 1)
{
log.Warning(
$"Multiple default types found for the highest priority, using the first found: {string.Join(", ", defaultPriority.Select(pair => pair.Key.FullName))}");
}
var defaultType = defaultPriority.First();
log.Info($"Providing default type: {defaultType.Key.FullName}");
return new List<T> {TypeLibrary.Create<T>(defaultType.Key.TargetType)};
}
// Should not be reachable, unless not used properly
log.Warning("Nothing found to provide. Normally there should be at least an internal default type");
return new List<T>();
}
}