Created
April 4, 2011 20:42
-
-
Save robashton/902388 to your computer and use it in GitHub Desktop.
The model we're analysing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Instruction[] dynamicMethodCalls = ExtractDynamicMethodCallInstructions(); | |
| if (dynamicMethodCalls.Length == 0) { return; } | |
| Instruction[] cachedReflectedFields = ExtractInitialReflectedCachedFieldReferenceInstructions(); | |
| if (cachedReflectedFields.Length == 0) { return; } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| CREATE TABLE Users | |
| ( | |
| Id int Identity | |
| Username varchar(255) | |
| SomeId int | |
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public Instruction[] ExtractDynamicMethodCallInstructions() | |
| { | |
| return method.Body.Instructions | |
| .Where(x => x.OpCode.Code == Mono.Cecil.Cil.Code.Callvirt) | |
| .Where(x => x.Operand is MemberReference && ((MemberReference)(x.Operand)).Name == "Invoke") | |
| .ToArray(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public Instruction[] ExtractInitialReflectedCachedFieldReferenceInstructions() | |
| { | |
| return method.Body.Instructions | |
| .Where(x => x.OpCode.Code == Code.Ldsfld && x.Next.OpCode.Code == Code.Brtrue_S) | |
| .Where(x=> ((FieldReference)x.Operand).IsCachedReflectionField()) | |
| .ToArray(); | |
| } | |
| public static bool IsCachedReflectionField(this FieldReference definition) | |
| { | |
| var baseType = definition.FieldType.Resolve().BaseType; | |
| return baseType.FullName == typeof (System.Runtime.CompilerServices.CallSite).FullName; | |
| return false; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [Test] | |
| public void Simple_Query_Against_Table_Results_In_String_Property_With_Constant_Being_Discovered() | |
| { | |
| var scanner = new ModelScanner(); | |
| var model = scanner.CreateModelFromAssembly<Users>(); | |
| var table = model.Table("Users"); | |
| var property = table.Column("Username"); | |
| Assert.That(property.Type, Is.EqualTo(typeof(string))); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var references = cachedReflectedFields | |
| .Select(field => field.ParseToFieldReferenceCreation()) | |
| .Reverse<string>() | |
| .ToList<string>(); | |
| public static string ParseToFieldReferenceCreation(this Instruction fieldReference) | |
| { | |
| Instruction current = fieldReference; | |
| while(current != null && current.OpCode.Code != Code.Ldstr) | |
| { | |
| current = current.Next; | |
| } | |
| return (string)current.Operand; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [0]: {IL_0000: nop} | |
| [1]: {IL_0001: ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`4<System.Runtime.CompilerServices.CallSite,System.Object,System.String,System.Object>> Simple.Data.Generation.Tests.Model.Users/<CreateSomeViewModel>o__SiteContainer0::<>p__Site1} | |
| [2]: {IL_0006: brtrue.s IL_0046} | |
| [3]: {IL_0008: ldc.i4.0} | |
| [4]: {IL_0009: ldstr "FindByUsername"} | |
| [5]: {IL_000e: ldnull} | |
| [6]: {IL_000f: ldtoken Simple.Data.Generation.Tests.Model.Users} | |
| [7]: {IL_0014: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)} | |
| [8]: {IL_0019: ldc.i4.2} | |
| [9]: {IL_001a: newarr Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo} | |
| [10]: {IL_001f: stloc.1} | |
| [11]: {IL_0020: ldloc.1} | |
| [12]: {IL_0021: ldc.i4.0} | |
| [13]: {IL_0022: ldc.i4.0} | |
| [14]: {IL_0023: ldnull} | |
| [15]: {IL_0024: call Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,System.String)} | |
| [16]: {IL_0029: stelem.ref} | |
| [17]: {IL_002a: ldloc.1} | |
| [18]: {IL_002b: ldc.i4.1} | |
| [19]: {IL_002c: ldc.i4.3} | |
| [20]: {IL_002d: ldnull} | |
| [21]: {IL_002e: call Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,System.String)} | |
| [22]: {IL_0033: stelem.ref} | |
| [23]: {IL_0034: ldloc.1} | |
| [24]: {IL_0035: call System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder::InvokeMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,System.String,System.Collections.Generic.IEnumerable`1<System.Type>,System.Type,System.Collections.Generic.IEnumerable`1<Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)} | |
| [25]: {IL_003a: call System.Runtime.CompilerServices.CallSite`1<!0> System.Runtime.CompilerServices.CallSite`1<System.Func`4<System.Runtime.CompilerServices.CallSite,System.Object,System.String,System.Object>>::Create(System.Runtime.CompilerServices.CallSiteBinder)} | |
| [26]: {IL_003f: stsfld System.Runtime.CompilerServices.CallSite`1<System.Func`4<System.Runtime.CompilerServices.CallSite,System.Object,System.String,System.Object>> Simple.Data.Generation.Tests.Model.Users/<CreateSomeViewModel>o__SiteContainer0::<>p__Site1} | |
| [27]: {IL_0044: br.s IL_0046} | |
| [28]: {IL_0046: ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`4<System.Runtime.CompilerServices.CallSite,System.Object,System.String,System.Object>> Simple.Data.Generation.Tests.Model.Users/<CreateSomeViewModel>o__SiteContainer0::<>p__Site1} | |
| [29]: {IL_004b: ldfld !0 System.Runtime.CompilerServices.CallSite`1<System.Func`4<System.Runtime.CompilerServices.CallSite,System.Object,System.String,System.Object>>::Target} | |
| [30]: {IL_0050: ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`4<System.Runtime.CompilerServices.CallSite,System.Object,System.String,System.Object>> Simple.Data.Generation.Tests.Model.Users/<CreateSomeViewModel>o__SiteContainer0::<>p__Site1} | |
| [31]: {IL_0055: ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object>> Simple.Data.Generation.Tests.Model.Users/<CreateSomeViewModel>o__SiteContainer0::<>p__Site2} | |
| [32]: {IL_005a: brtrue.s IL_008f} | |
| [33]: {IL_005c: ldc.i4.0} | |
| [34]: {IL_005d: ldstr "Users"} | |
| [35]: {IL_0062: ldtoken Simple.Data.Generation.Tests.Model.Users} | |
| [36]: {IL_0067: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)} | |
| [37]: {IL_006c: ldc.i4.1} | |
| [38]: {IL_006d: newarr Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo} | |
| [39]: {IL_0072: stloc.1} | |
| [40]: {IL_0073: ldloc.1} | |
| [41]: {IL_0074: ldc.i4.0} | |
| [42]: {IL_0075: ldc.i4.0} | |
| [43]: {IL_0076: ldnull} | |
| [44]: {IL_0077: call Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,System.String)} | |
| [45]: {IL_007c: stelem.ref} | |
| [46]: {IL_007d: ldloc.1} | |
| [47]: {IL_007e: call System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder::GetMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,System.String,System.Type,System.Collections.Generic.IEnumerable`1<Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)} | |
| [48]: {IL_0083: call System.Runtime.CompilerServices.CallSite`1<!0> System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object>>::Create(System.Runtime.CompilerServices.CallSiteBinder)} | |
| [49]: {IL_0088: stsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object>> Simple.Data.Generation.Tests.Model.Users/<CreateSomeViewModel>o__SiteContainer0::<>p__Site2} | |
| [50]: {IL_008d: br.s IL_008f} | |
| [51]: {IL_008f: ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object>> Simple.Data.Generation.Tests.Model.Users/<CreateSomeViewModel>o__SiteContainer0::<>p__Site2} | |
| [52]: {IL_0094: ldfld !0 System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object>>::Target} | |
| [53]: {IL_0099: ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object>> Simple.Data.Generation.Tests.Model.Users/<CreateSomeViewModel>o__SiteContainer0::<>p__Site2} | |
| [54]: {IL_009e: ldarg.0} | |
| [55]: {IL_009f: ldfld System.Object Simple.Data.Generation.Tests.Model.Users::db} | |
| [56]: {IL_00a4: callvirt !2 System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object>::Invoke(!0,!1)} | |
| [57]: {IL_00a9: ldstr "bob"} | |
| [58]: {IL_00ae: callvirt !3 System.Func`4<System.Runtime.CompilerServices.CallSite,System.Object,System.String,System.Object>::Invoke(!0,!1,!2)} | |
| [59]: {IL_00b3: stloc.0} | |
| [60]: {IL_00b4: br.s IL_00b6} | |
| [61]: {IL_00b6: ldloc.0} | |
| [62]: {IL_00b7: ret} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public void PopulateDataModel(DataModel model) | |
| { | |
| definition.Methods | |
| .Select(method =>new MethodInspector(method)).ToList() | |
| .ForEach(inspector => inspector.PopulateDataModel(model)); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class Users | |
| { | |
| private dynamic db = Database.Open(); | |
| public dynamic CreateSomeViewModel() | |
| { | |
| return db.Users.FindByUsername("bob"); | |
| } | |
| public dynamic CreateAnotherViewModel() | |
| { | |
| return db.Users.FindBySomeId(4); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class ModelScanner | |
| { | |
| public DataModel CreateModelFromAssembly<T>() | |
| { | |
| var model = new DataModel(); | |
| var assembly = typeof(T).Assembly; | |
| var assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(assembly.Location); | |
| assemblyDefinition.MainModule.Types | |
| .Select(type => new TypeInspector(type)) | |
| .ToList() | |
| .ForEach(inspector => inspector.PopulateDataModel(model)); | |
| return model; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment