-
Notifications
You must be signed in to change notification settings - Fork 1
/
ClassManager.cs
106 lines (95 loc) · 3.57 KB
/
ClassManager.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
/* Copyright (c) 2018-2024 Nuno Fachada and contributors
* Distributed under the MIT License (See accompanying file LICENSE or copy
* at http://opensource.org/licenses/MIT) */
using System;
using System.Collections.Generic;
using System.Linq;
namespace LibGameAI.Util
{
/// <summary>
/// Singleton class used for finding and keeping a record of concrete
/// classes of a given generic type.
/// </summary>
public class ClassManager<T>
{
// Unique instance of this class, instantiated lazily
private static readonly Lazy<ClassManager<T>> instance =
new Lazy<ClassManager<T>>(() => new ClassManager<T>());
// Known classes of type T
private IDictionary<string, Type> knownTypes;
/// <summary>
/// Returns the singleton instance of this class.
/// </summary>
/// <value>The singleton instance of this class.</value>
public static ClassManager<T> Instance => instance.Value;
/// <summary>
/// Array of class names.
/// </summary>
/// <value>Names of known classes of type T.</value>
public string[] ClassNames => knownTypes.Keys.ToArray();
/// <summary>
/// Get class type from class name.
/// </summary>
/// <param name="name">
/// Name of class.
/// </param>
/// <returns>
/// The class's type.
/// </returns>
public Type GetTypeFromName(string name) => knownTypes[name];
/// <summary>
/// Get name from type.
/// </summary>
/// <param name="type">Type of class.</param>
/// <returns>Name of class.</returns>
public string GetNameFromType(Type type)
{
foreach (KeyValuePair<string, Type> kvp in knownTypes)
{
if (kvp.Value.Equals(type))
{
return kvp.Key;
}
}
return null;
}
/// <summary>
/// Replace default names with which the classes are known.
/// </summary>
/// <param name="replacer">Delegate to perform name replacement.</param>
/// <returns>This instance, for use in fluent syntax.</returns>
public ClassManager<T> ReplaceNames(Func<string, string> replacer)
{
knownTypes = knownTypes
.ToDictionary(kvp => replacer(kvp.Key), kvp => kvp.Value);
return this;
}
/// <summary>
/// Filter out types that are not of interest to the client.
/// </summary>
/// <param name="filter">
/// Filter to apply, returns <c>true</c> if class is to keep, or
/// <c>false</c> otherwise.
/// </param>
/// <returns>This instance, for use in fluent syntax.</returns>
public ClassManager<T> FilterTypes(Func<Type, bool> filter)
{
knownTypes = knownTypes
.Where(kvp => filter(kvp.Value))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
return this;
}
// Private constructor
private ClassManager()
{
// Get a reference to the class type
Type classType = typeof(T);
// Get classes which extend or implement T and are not abstract
knownTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => !t.IsAbstract &&
(t.IsSubclassOf(classType) || classType.IsAssignableFrom(t)))
.ToDictionary(t => t.FullName, t => t);
}
}
}