Skip to content

Commit a2ff273

Browse files
committed
Added caching to Injector. When attempting to inject into a type after the first time it will use cached values for the properties and fields instead of doing reflection every time.
Added some nice helper functions to Binding: Access and modify binds quicker with [] operator overload Clear all binds with .Clear() Clear specific binds with .Clear(T) Get an array of all bindings with .ToArray() Get number of bindings with .Count Modified Scene/SceneObjectData and Factory to use Bindings instead of a Dictionary
1 parent eb7846e commit a2ff273

File tree

5 files changed

+148
-71
lines changed

5 files changed

+148
-71
lines changed

Assets/CleaveFramework/Binding/Binding.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,50 @@ public bool IsBound(T type)
103103
return Bindings.ContainsKey(type);
104104
}
105105

106+
/// <summary>
107+
/// removes all bindings from the library
108+
/// </summary>
109+
public void Clear()
110+
{
111+
Bindings.Clear();
112+
}
113+
114+
/// <summary>
115+
/// removes binding of type from the library
116+
/// </summary>
117+
/// <param name="type"></param>
118+
public void Clear(T type)
119+
{
120+
Bindings.Remove(type);
121+
}
122+
123+
/// <summary>
124+
/// return the bindings library as an associative array
125+
/// </summary>
126+
/// <returns></returns>
127+
public KeyValuePair<T, V>[] ToArray()
128+
{
129+
return Bindings.ToArray();
130+
}
131+
132+
/// <summary>
133+
/// return the number of total bindings in the library
134+
/// </summary>
135+
public int Count
136+
{
137+
get { return Bindings.Count; }
138+
}
139+
140+
/// <summary>
141+
/// [] operator overload
142+
/// </summary>
143+
/// <param name="type"></param>
144+
/// <returns></returns>
145+
public V this[T type]
146+
{
147+
get { return Resolve(type); }
148+
set { Bind(type, value); }
149+
}
106150
}
151+
107152
}

Assets/CleaveFramework/Core/Framework.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static string TransitionScene
4545
void Awake()
4646
{
4747
CDebug.DisplayMethod = CDebug.ConsoleLogMethod.Selected;
48-
CDebug.LogThis(typeof(Injector));
48+
//CDebug.LogThis(typeof(Injector));
4949

5050
if (Instance != this && Instance != null)
5151
{

Assets/CleaveFramework/Dependency Inject/Injector.cs

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ You may obtain a copy of the License at
1212
See the License for the specific language governing permissions and
1313
limitations under the License. */
1414
using System;
15+
using System.Collections;
16+
using System.Collections.Generic;
1517
using System.Linq;
1618
using System.Reflection;
1719
using CleaveFramework.Binding;
@@ -55,9 +57,12 @@ private enum InjectTypes
5557

5658
private static Binding<Type, InjectTypes> _injectionTypes = new Binding<Type, InjectTypes>();
5759
private static Binding<Type, object> _singletons = new Binding<Type, object>();
58-
5960
private static Binding<Type, Type> _transients = new Binding<Type, Type>();
6061

62+
private static Binding<Type, IEnumerable<FieldInfo>> _fieldsCache = new Binding<Type, IEnumerable<FieldInfo>>();
63+
private static Binding<Type, IEnumerable<PropertyInfo>> _propertyCache = new Binding<Type, IEnumerable<PropertyInfo>>();
64+
private static Binding<Type, IEnumerable<MemberInfo>> _memberCache = new Binding<Type, IEnumerable<MemberInfo>>();
65+
6166
/// <summary>
6267
/// Add a Transient type to the Injector and map it to a specific implementation
6368
/// </summary>
@@ -117,11 +122,23 @@ private static object Resolve(Type t)
117122

118123
private static void InjectProperties<T>(T obj)
119124
{
120-
var props = typeof(T).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(Inject)));
125+
var injectingType = typeof (T);
126+
127+
IEnumerable<PropertyInfo> props;
128+
if (_propertyCache.IsBound(injectingType))
129+
{
130+
props = _propertyCache.Resolve(injectingType);
131+
}
132+
else
133+
{
134+
props = injectingType.GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(Inject)));
135+
_propertyCache.Bind(injectingType, props);
136+
}
137+
CDebug.Assert(props == null, "Injector.InjectProperties()");
138+
121139
foreach (var cProp in props)
122140
{
123141
if (!cProp.CanWrite) continue;
124-
125142
CDebug.Log("Injector.InjectProperties<" + cProp.PropertyType + "> on " + obj);
126143
var instance = Resolve(cProp.PropertyType);
127144
cProp.SetValue(obj, instance, null);
@@ -130,7 +147,21 @@ private static void InjectProperties<T>(T obj)
130147

131148
private static void InjectFields<T>(T obj)
132149
{
133-
var fields = typeof(T).GetFields().Where(prop => Attribute.IsDefined(prop, typeof(Inject)));
150+
151+
var injectingType = typeof(T);
152+
153+
IEnumerable<FieldInfo> fields;
154+
if (_fieldsCache.IsBound(injectingType))
155+
{
156+
fields = _fieldsCache.Resolve(injectingType);
157+
}
158+
else
159+
{
160+
fields = injectingType.GetFields().Where(prop => Attribute.IsDefined(prop, typeof(Inject)));
161+
_fieldsCache.Bind(injectingType, fields);
162+
}
163+
CDebug.Assert(fields == null, "Injector.InjectFields()");
164+
134165
foreach (var cField in fields)
135166
{
136167
CDebug.Log("Injector.InjectFields<" + cField.FieldType + "> on " + obj);
@@ -142,12 +173,27 @@ private static void InjectFields<T>(T obj)
142173
private static void InjectMonoBehaviour<T>(T obj)
143174
{
144175
var monoObj = obj as MonoBehaviour;
145-
var monoFields = monoObj.GetType().GetMembers().Where(prop => Attribute.IsDefined(prop, typeof(Inject)));
146-
foreach (FieldInfo monoField in monoFields)
176+
177+
var injectingType = monoObj.GetType();
178+
179+
IEnumerable<MemberInfo> members;
180+
if (_memberCache.IsBound(injectingType))
147181
{
148-
CDebug.Log("Injector.InjectMonoBehaviour<" + monoField.FieldType + "> on " + obj);
149-
var instance = Resolve(monoField.FieldType);
150-
monoField.SetValue(monoObj, instance);
182+
members = _memberCache.Resolve(injectingType);
183+
}
184+
else
185+
{
186+
members = injectingType.GetMembers().Where(prop => Attribute.IsDefined(prop, typeof(Inject)));
187+
_memberCache.Bind(injectingType, members);
188+
}
189+
CDebug.Assert(members == null, "Injector.InjectMonoBehaviour()");
190+
191+
// for some reason MonoBehaviour members need to be addressed as fields.
192+
foreach (FieldInfo cField in members)
193+
{
194+
CDebug.Log("Injector.InjectMonoBehaviour<" + cField.FieldType + "> on " + obj);
195+
var instance = Resolve(cField.FieldType);
196+
cField.SetValue(monoObj, instance);
151197
}
152198
}
153199

Assets/CleaveFramework/Factory/Factory.cs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ You may obtain a copy of the License at
1212
See the License for the specific language governing permissions and
1313
limitations under the License. */
1414
using System;
15-
using System.Collections.Generic;
15+
using CleaveFramework.Binding;
1616
using CleaveFramework.DependencyInjection;
1717
using CleaveFramework.Scene;
1818
using CleaveFramework.Tools;
@@ -32,7 +32,7 @@ namespace CleaveFramework.Factory
3232
/// </summary>
3333
static class Factory
3434
{
35-
static Dictionary<Type, Constructor> _constructors = new Dictionary<Type, Constructor>();
35+
static Binding<Type, Constructor> _constructors = new Binding<Type,Constructor>();
3636

3737
/// <summary>
3838
/// Sets a post instantiation constructor to an object type
@@ -41,13 +41,7 @@ static class Factory
4141
/// <param name="constructor">delegate to act as constructor</param>
4242
static public void SetConstructor<T>(Constructor constructor)
4343
{
44-
// for now we are a single delegate
45-
if (_constructors.ContainsKey(typeof (T)))
46-
{
47-
_constructors[typeof (T)] = constructor;
48-
return;
49-
}
50-
_constructors.Add(typeof(T), constructor);
44+
_constructors[typeof (T)] = constructor;
5145
}
5246

5347
/// <summary>
@@ -473,7 +467,7 @@ static public object Create(Type t)
473467
{
474468
var obj = Activator.CreateInstance(t);
475469
obj = Injector.PerformInjections(obj);
476-
if (_constructors.ContainsKey(t))
470+
if (_constructors.IsBound(t))
477471
{
478472
_constructors[t].Invoke(obj);
479473
}
@@ -581,12 +575,9 @@ static private object InvokeConstructor<T>(object obj, Constructor constructor)
581575

582576
static private object InvokeDefaultConstructor<T>(object obj)
583577
{
584-
if (_constructors.ContainsKey(typeof(T)))
585-
{
586-
if (_constructors[typeof(T)] != null)
587-
obj = (T)_constructors[typeof(T)].Invoke(obj);
588-
}
589-
return obj;
578+
var objType = typeof (T);
579+
if (!_constructors.IsBound(objType)) return obj;
580+
return (T)_constructors[objType].Invoke(obj);
590581
}
591582

592583
static private GameObject ResolveGameObject(string goName)

Assets/CleaveFramework/Scene/SceneObjectData.cs

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using CleaveFramework.Interfaces;
44
using CleaveFramework.Tools;
5+
using CleaveFramework.Binding;
56

67
namespace CleaveFramework.Scene
78
{
@@ -13,51 +14,44 @@ public sealed class SceneObjectData
1314
/// <summary>
1415
/// singleton library
1516
/// </summary>
16-
private Dictionary<Type, object> _singletons;
17+
//private Dictionary<Type, object> _singletons;
18+
private Binding<Type, object> _singletons = new Binding<Type,object>();
1719

1820
/// <summary>
1921
/// transient objects library
2022
/// </summary>
21-
private Dictionary<Type, Dictionary<string, object>> _transients;
23+
//private Dictionary<Type, Dictionary<string, object>> _transients;
24+
private Binding<Type, Binding<string, object>> _transients = new Binding<Type, Binding<string, object>>();
2225

2326
/// <summary>
2427
/// IUpdateable objects library
2528
/// </summary>
26-
private List<IUpdateable> _updateables;
29+
private List<IUpdateable> _updateables = new List<IUpdateable>();
2730

2831
/// <summary>
2932
/// IInitializeable objects library
3033
/// </summary>
31-
private List<IInitializeable> _initializeables;
34+
private List<IInitializeable> _initializeables = new List<IInitializeable>();
3235

3336
/// <summary>
3437
/// IConfigureable objects library
3538
/// </summary>
36-
private List<IConfigureable> _configureables;
39+
private List<IConfigureable> _configureables = new List<IConfigureable>();
3740

3841
/// <summary>
3942
/// IConfigureable objects library
4043
/// </summary>
41-
private List<IDestroyable> _destroyables;
44+
private List<IDestroyable> _destroyables = new List<IDestroyable>();
4245

4346
public bool IsObjectDataInitialized { get; private set; }
4447

4548
public SceneObjectData()
4649
{
47-
_singletons = new Dictionary<Type, object>();
48-
_transients = new Dictionary<Type, Dictionary<string, object>>();
49-
_updateables = new List<IUpdateable>();
50-
_initializeables = new List<IInitializeable>();
51-
_configureables = new List<IConfigureable>();
52-
_destroyables = new List<IDestroyable>();
5350
IsObjectDataInitialized = false;
54-
//CDebug.LogThis(typeof(SceneObjectData));
5551
}
5652

5753
public void Destroy()
5854
{
59-
CDebug.Log("SceneObjectData::Destroy()");
60-
6155
foreach (var obj in _destroyables)
6256
{
6357
obj.Destroy();
@@ -140,6 +134,16 @@ private static void ReflectInterfaces<T>(SceneObjectData instance, T obj)
140134
}
141135
}
142136

137+
/// <summary>
138+
/// Injects an object instance into the framework singleton library
139+
/// </summary>
140+
/// <typeparam name="T">object type</typeparam>
141+
/// <param name="obj">object instance</param>
142+
public object PushSingleton<T>(T obj)
143+
{
144+
return PushObjectAsSingleton(obj);
145+
}
146+
143147
/// <summary>
144148
/// Injects an object instance into the framework singleton library
145149
/// </summary>
@@ -149,18 +153,7 @@ public object PushObjectAsSingleton<T>(T obj)
149153
{
150154
// reflect on the implemented interfaces
151155
ReflectInterfaces(this, obj);
152-
153-
if (!_singletons.ContainsKey(typeof(T)))
154-
{
155-
// insert object into the library
156-
_singletons.Add(typeof(T), obj);
157-
}
158-
else
159-
{
160-
// overwrite existing object with new instance
161-
_singletons[typeof(T)] = obj;
162-
}
163-
156+
_singletons[typeof (T)] = obj;
164157
return obj;
165158
}
166159

@@ -171,7 +164,18 @@ public object PushObjectAsSingleton<T>(T obj)
171164
/// <returns>object instance if injected, otherwise null</returns>
172165
public object ResolveSingleton<T>()
173166
{
174-
return _singletons.ContainsKey(typeof(T)) ? _singletons[typeof(T)] : null;
167+
return _singletons[typeof (T)];
168+
}
169+
170+
/// <summary>
171+
/// Inject an object instance into the framework transients library
172+
/// </summary>
173+
/// <typeparam name="T">object type</typeparam>
174+
/// <param name="name">object instance name, required for lookup and must be unique per type</param>
175+
/// <param name="obj">object instance</param>
176+
public object PushTransient<T>(string name, T obj)
177+
{
178+
return PushObjectAsTransient(name, obj);
175179
}
176180

177181
/// <summary>
@@ -184,20 +188,17 @@ public object PushObjectAsTransient<T>(string name, T obj)
184188
{
185189
ReflectInterfaces(this, obj);
186190

187-
if (!_transients.ContainsKey(typeof (T)))
188-
{
189-
_transients.Add(typeof(T), new Dictionary<string, object>());
190-
}
191-
192-
if (_transients[typeof (T)].ContainsKey(name))
191+
var objType = typeof (T);
192+
if (!_transients.IsBound(objType))
193193
{
194-
throw new Exception("Object instance type/name combination is not unique: " + typeof(T).ToString() + "/" + name);
194+
_transients.Bind(objType, new Binding<string, object>());
195195
}
196196

197-
_transients[typeof(T)].Add(name, obj);
197+
CDebug.Assert(_transients[objType].IsBound(name),
198+
"Object instance type/name combination is not unique: " + objType + "/" + name);
198199

200+
_transients[objType][name] = obj;
199201
return obj;
200-
201202
}
202203

203204
/// <summary>
@@ -208,14 +209,8 @@ public object PushObjectAsTransient<T>(string name, T obj)
208209
/// <returns>object instance</returns>
209210
public object ResolveTransient<T>(string name)
210211
{
211-
if (!_transients.ContainsKey(typeof (T)))
212-
{
213-
return null;
214-
}
215-
return !_transients[typeof (T)].ContainsKey(name) ? null : _transients[typeof (T)][name];
212+
var objType = typeof (T);
213+
return !_transients.IsBound(objType) ? null : _transients[objType][name];
216214
}
217-
218-
219-
220215
}
221216
}

0 commit comments

Comments
 (0)