StrangeIoC is a library that can help you build your Unity app with a “pure code” approach. Today’s article addresses one common concern with using StrangeIoC- it uses a lot of reflection. As we know, that’s really slow in Unity. StrangeIoC tries to work around it by letting you control when the reflection takes place so you can put it on a loading screen or some other convenient place. Today’s article finds out just how slow the reflection is to determine if this is really a valid reason to not use StrangeIoC (or other dependency injection frameworks). Read on to find out!

StrangeIoC’s support for reflecting classes ahead of time in a controlled way also gives us the ability to set up a test to see how slow it is. Here is how we can test the reflection time:

// List all the types to reflect
var types = new List<Type>()
{
	typeof(TestClass0),
	typeof(TestClass1),
	typeof(TestClass2)
};
 
// Create the injection binder that will do the reflecting
var binder = new strange.extensions.injector.impl.InjectionBinder();
 
// Start the timer
var stopwatch = new Stopwatch();
stopwatch.Start();
 
// Reflect all the types
binder.Reflect(types);
 
// Record the time
var time = stopwatch.ElapsedMilliseconds;

The next step is to come up with some classes to reflect. A full game or app will have lots of classes to reflect, but my test app is nearly empty. I therefore need to create dummy classes to mimic a real app. Since apps vary in size and complexity, I necessarily chose an arbitrary number of classes.

StrangeIoC reflects three things—types, constructors, and properties—because they are the only things used in dependency injection. To test these, I gave each of my test classes an arbitrary number of constructors and properties.

In the end I decided on what seemed like reasonable numbers of classes, constructors, and properties for a medium-sized app. I chose to have 100 classes, each with two constructors and four properties. That’s probably not what your app looks like, so I’d recommend doing the test with your own code using binder.ReflectAll(). Regardless, here’s my test class pattern:

private class TestClass0
{
	public TestClass0(){}
	public TestClass0(int a){}
	public int A { get; set; }
	public int B { get; set; }
	public int C { get; set; }
	public int D { get; set; }
}

And here’s the full test app:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
 
using UnityEngine;
 
public class TestScript : MonoBehaviour
{
	private string report;
 
	private class TestClass0
	{
		public TestClass0(){}
		public TestClass0(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass1
	{
		public TestClass1(){}
		public TestClass1(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass2
	{
		public TestClass2(){}
		public TestClass2(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass3
	{
		public TestClass3(){}
		public TestClass3(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass4
	{
		public TestClass4(){}
		public TestClass4(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass5
	{
		public TestClass5(){}
		public TestClass5(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass6
	{
		public TestClass6(){}
		public TestClass6(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass7
	{
		public TestClass7(){}
		public TestClass7(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass8
	{
		public TestClass8(){}
		public TestClass8(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass9
	{
		public TestClass9(){}
		public TestClass9(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass10
	{
		public TestClass10(){}
		public TestClass10(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass11
	{
		public TestClass11(){}
		public TestClass11(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass12
	{
		public TestClass12(){}
		public TestClass12(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass13
	{
		public TestClass13(){}
		public TestClass13(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass14
	{
		public TestClass14(){}
		public TestClass14(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass15
	{
		public TestClass15(){}
		public TestClass15(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass16
	{
		public TestClass16(){}
		public TestClass16(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass17
	{
		public TestClass17(){}
		public TestClass17(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass18
	{
		public TestClass18(){}
		public TestClass18(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass19
	{
		public TestClass19(){}
		public TestClass19(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass20
	{
		public TestClass20(){}
		public TestClass20(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass21
	{
		public TestClass21(){}
		public TestClass21(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass22
	{
		public TestClass22(){}
		public TestClass22(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass23
	{
		public TestClass23(){}
		public TestClass23(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass24
	{
		public TestClass24(){}
		public TestClass24(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass25
	{
		public TestClass25(){}
		public TestClass25(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass26
	{
		public TestClass26(){}
		public TestClass26(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass27
	{
		public TestClass27(){}
		public TestClass27(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass28
	{
		public TestClass28(){}
		public TestClass28(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass29
	{
		public TestClass29(){}
		public TestClass29(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass30
	{
		public TestClass30(){}
		public TestClass30(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass31
	{
		public TestClass31(){}
		public TestClass31(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass32
	{
		public TestClass32(){}
		public TestClass32(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass33
	{
		public TestClass33(){}
		public TestClass33(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass34
	{
		public TestClass34(){}
		public TestClass34(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass35
	{
		public TestClass35(){}
		public TestClass35(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass36
	{
		public TestClass36(){}
		public TestClass36(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass37
	{
		public TestClass37(){}
		public TestClass37(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass38
	{
		public TestClass38(){}
		public TestClass38(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass39
	{
		public TestClass39(){}
		public TestClass39(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass40
	{
		public TestClass40(){}
		public TestClass40(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass41
	{
		public TestClass41(){}
		public TestClass41(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass42
	{
		public TestClass42(){}
		public TestClass42(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass43
	{
		public TestClass43(){}
		public TestClass43(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass44
	{
		public TestClass44(){}
		public TestClass44(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass45
	{
		public TestClass45(){}
		public TestClass45(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass46
	{
		public TestClass46(){}
		public TestClass46(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass47
	{
		public TestClass47(){}
		public TestClass47(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass48
	{
		public TestClass48(){}
		public TestClass48(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass49
	{
		public TestClass49(){}
		public TestClass49(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass50
	{
		public TestClass50(){}
		public TestClass50(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass51
	{
		public TestClass51(){}
		public TestClass51(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass52
	{
		public TestClass52(){}
		public TestClass52(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass53
	{
		public TestClass53(){}
		public TestClass53(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass54
	{
		public TestClass54(){}
		public TestClass54(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass55
	{
		public TestClass55(){}
		public TestClass55(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass56
	{
		public TestClass56(){}
		public TestClass56(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass57
	{
		public TestClass57(){}
		public TestClass57(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass58
	{
		public TestClass58(){}
		public TestClass58(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass59
	{
		public TestClass59(){}
		public TestClass59(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass60
	{
		public TestClass60(){}
		public TestClass60(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass61
	{
		public TestClass61(){}
		public TestClass61(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass62
	{
		public TestClass62(){}
		public TestClass62(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass63
	{
		public TestClass63(){}
		public TestClass63(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass64
	{
		public TestClass64(){}
		public TestClass64(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass65
	{
		public TestClass65(){}
		public TestClass65(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass66
	{
		public TestClass66(){}
		public TestClass66(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass67
	{
		public TestClass67(){}
		public TestClass67(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass68
	{
		public TestClass68(){}
		public TestClass68(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass69
	{
		public TestClass69(){}
		public TestClass69(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass70
	{
		public TestClass70(){}
		public TestClass70(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass71
	{
		public TestClass71(){}
		public TestClass71(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass72
	{
		public TestClass72(){}
		public TestClass72(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass73
	{
		public TestClass73(){}
		public TestClass73(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass74
	{
		public TestClass74(){}
		public TestClass74(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass75
	{
		public TestClass75(){}
		public TestClass75(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass76
	{
		public TestClass76(){}
		public TestClass76(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass77
	{
		public TestClass77(){}
		public TestClass77(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass78
	{
		public TestClass78(){}
		public TestClass78(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass79
	{
		public TestClass79(){}
		public TestClass79(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass80
	{
		public TestClass80(){}
		public TestClass80(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass81
	{
		public TestClass81(){}
		public TestClass81(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass82
	{
		public TestClass82(){}
		public TestClass82(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass83
	{
		public TestClass83(){}
		public TestClass83(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass84
	{
		public TestClass84(){}
		public TestClass84(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass85
	{
		public TestClass85(){}
		public TestClass85(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass86
	{
		public TestClass86(){}
		public TestClass86(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass87
	{
		public TestClass87(){}
		public TestClass87(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass88
	{
		public TestClass88(){}
		public TestClass88(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass89
	{
		public TestClass89(){}
		public TestClass89(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass90
	{
		public TestClass90(){}
		public TestClass90(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass91
	{
		public TestClass91(){}
		public TestClass91(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass92
	{
		public TestClass92(){}
		public TestClass92(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass93
	{
		public TestClass93(){}
		public TestClass93(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass94
	{
		public TestClass94(){}
		public TestClass94(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass95
	{
		public TestClass95(){}
		public TestClass95(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass96
	{
		public TestClass96(){}
		public TestClass96(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass97
	{
		public TestClass97(){}
		public TestClass97(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass98
	{
		public TestClass98(){}
		public TestClass98(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	private class TestClass99
	{
		public TestClass99(){}
		public TestClass99(int a){}
		public int A { get; set; }
		public int B { get; set; }
		public int C { get; set; }
		public int D { get; set; }
	}
 
	void Start()
	{
		var types = new List<Type>()
		{
			typeof(TestClass0),
			typeof(TestClass1),
			typeof(TestClass2),
			typeof(TestClass3),
			typeof(TestClass4),
			typeof(TestClass5),
			typeof(TestClass6),
			typeof(TestClass7),
			typeof(TestClass8),
			typeof(TestClass9),
			typeof(TestClass10),
			typeof(TestClass11),
			typeof(TestClass12),
			typeof(TestClass13),
			typeof(TestClass14),
			typeof(TestClass15),
			typeof(TestClass16),
			typeof(TestClass17),
			typeof(TestClass18),
			typeof(TestClass19),
			typeof(TestClass20),
			typeof(TestClass21),
			typeof(TestClass22),
			typeof(TestClass23),
			typeof(TestClass24),
			typeof(TestClass25),
			typeof(TestClass26),
			typeof(TestClass27),
			typeof(TestClass28),
			typeof(TestClass29),
			typeof(TestClass30),
			typeof(TestClass31),
			typeof(TestClass32),
			typeof(TestClass33),
			typeof(TestClass34),
			typeof(TestClass35),
			typeof(TestClass36),
			typeof(TestClass37),
			typeof(TestClass38),
			typeof(TestClass39),
			typeof(TestClass40),
			typeof(TestClass41),
			typeof(TestClass42),
			typeof(TestClass43),
			typeof(TestClass44),
			typeof(TestClass45),
			typeof(TestClass46),
			typeof(TestClass47),
			typeof(TestClass48),
			typeof(TestClass49),
			typeof(TestClass50),
			typeof(TestClass51),
			typeof(TestClass52),
			typeof(TestClass53),
			typeof(TestClass54),
			typeof(TestClass55),
			typeof(TestClass56),
			typeof(TestClass57),
			typeof(TestClass58),
			typeof(TestClass59),
			typeof(TestClass60),
			typeof(TestClass61),
			typeof(TestClass62),
			typeof(TestClass63),
			typeof(TestClass64),
			typeof(TestClass65),
			typeof(TestClass66),
			typeof(TestClass67),
			typeof(TestClass68),
			typeof(TestClass69),
			typeof(TestClass70),
			typeof(TestClass71),
			typeof(TestClass72),
			typeof(TestClass73),
			typeof(TestClass74),
			typeof(TestClass75),
			typeof(TestClass76),
			typeof(TestClass77),
			typeof(TestClass78),
			typeof(TestClass79),
			typeof(TestClass80),
			typeof(TestClass81),
			typeof(TestClass82),
			typeof(TestClass83),
			typeof(TestClass84),
			typeof(TestClass85),
			typeof(TestClass86),
			typeof(TestClass87),
			typeof(TestClass88),
			typeof(TestClass89),
			typeof(TestClass90),
			typeof(TestClass91),
			typeof(TestClass92),
			typeof(TestClass93),
			typeof(TestClass94),
			typeof(TestClass95),
			typeof(TestClass96),
			typeof(TestClass97),
			typeof(TestClass98),
			typeof(TestClass99)
		};
		var binder = new strange.extensions.injector.impl.InjectionBinder();
		var stopwatch = new Stopwatch();
		stopwatch.Start();
		binder.Reflect(types);
		var time = stopwatch.ElapsedMilliseconds;
		report = time.ToString();
	}
 
	void OnGUI()
	{
		GUI.TextArea(new Rect(0, 0, Screen.width, Screen.height), report);
	}
}

If you want to try out the test yourself, simply paste the above code into a TestScript.cs file in your Unity project’s Assets directory and attach it to the main camera game object in a new, empty project. Then build in non-development mode for 64-bit processors and run it windowed at 640×480 with fastest graphics. I ran it that way on this machine:

  • 2.3 Ghz Intel Core i7-3615QM
  • Mac OS X 10.10.3
  • Unity 5.1.0f3, Mac OS X Standalone, x86_64, non-development
  • 640×480, Fastest, Windowed

My result: 17 milliseconds to reflect all the classes.

Is that fast enough? Considering that a single frame of a game at 30 FPS is about 33 milliseconds, you’d use up about half the frame just reflecting. If you’re shooting for 60 FPS or more—such as for a VR headset—then your frame will be less than the 17 milliseconds required. If your processor is slower than my Core i7—like with mobile CPUs—then you’ll take much longer than 17 milliseconds to do the reflection.

So it seems to me that you’ll probably want to spread the reflection out over multiple frames to avoid any hitches in frame rate. Unfortunately, this isn’t made very easy. StrangeIoC only provides two methods to control the reflection. You either give it an explicit list of types to reflect or you reflect everything. So if you want to spread the work out across frames you need to make several lists of types and hope that each list has just enough so that it doesn’t take too long on the frame that it runs. That’s not very likely.

To make spreading out the reflection work over multiple frames easier, I’ve written a little class to provide two extension methods: ReflectOverTime and ReflectAllOverTime. Here’s a quick example:

// List all the types to reflect
var types = new List<Type>()
{
	typeof(TestClass0),
	typeof(TestClass1),
	typeof(TestClass2)
};
 
// Create the injection binder that will do the reflecting
var binder = new strange.extensions.injector.impl.InjectionBinder();
 
// Reflect for up to 5 milliseconds per frame as a coroutine
StartCoroutine(binder.ReflectOverTime(types, 5).GetEnumerator());

If you’d like to use this in your own projects, here’s the source code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
 
using strange.extensions.injector.api;
using strange.framework.api;
 
// Extension class for IInjectionBinder to reflect its bound types over time
// Author: Jackson Dunstan, http://JacksonDunstan.com/articles/3086
public static class IInjectionBinderReflectOverTime
{
	public static IEnumerable ReflectAllOverTime(
		this IInjectionBinder binder,
		int reflectionTimePerFrame
	)
	{
		var stopwatch = new Stopwatch();
		stopwatch.Start();
		var types = new List<Type>();
		var bindings = GetBindings(binder);
		foreach (var pair in bindings)
		{
			var dict = pair.Value;
			foreach (var bPair in dict)
			{
				var binding = bPair.Value as IBinding;
				var type = (binding.value is Type)
					? (Type)binding.value
					: binding.value.GetType();
				if (types.IndexOf(type) == -1)
				{
					types.Add(type);
				}
			}
		}
 
		return Reflect(binder, types, stopwatch, reflectionTimePerFrame);
	}
 
	public static IEnumerable ReflectOverTime(
		this IInjectionBinder binder,
		List<Type> types,
		int reflectionTimePerFrame
	)
	{
		var stopwatch = new Stopwatch();
		stopwatch.Start();
		foreach (var e in Reflect(binder, types, stopwatch, reflectionTimePerFrame))
		{
			yield return e;
		}
	}
 
	private static IEnumerable Reflect(
		IInjectionBinder binder,
		List<Type> types,
		Stopwatch stopwatch,
		int reflectionTimePerFrame
	)
	{
		foreach (var t in types)
		{
			// Reflector won't permit primitive types, so screen them
			if (t.IsPrimitive || t == typeof(Decimal) || t == typeof(string))
			{
				continue;
			}
			binder.injector.reflector.Get(t);
			if (stopwatch.ElapsedMilliseconds > reflectionTimePerFrame)
			{
				yield return null;
				stopwatch.Reset();
				stopwatch.Start();
			}
		}
	}
 
	// Get a Binder's bindings
	private static Dictionary <object, Dictionary<object, IBinding>>
		GetBindings(IInjectionBinder binder)
	{
		var flags = BindingFlags.NonPublic | BindingFlags.Instance;
		var bindingsField = typeof(Binder).GetField("bindings", flags);
		var bindings = bindingsField.GetValue(binder);
		return (Dictionary <object, Dictionary<object, IBinding>>)bindings;
	}
}

Hopefully this class will help alleviate the cost of reflection with StrangeIoC so you can use it if that was a blocking issue. The same strategy could be adapted to any expensive task in Unity that needs to be split across frames, including reflecting a lot of types.

Do you use StrangeIoC or a lot of reflection? How have you worked around it? Let me know your strategies in the comments!