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 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 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 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 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 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 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 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 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 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 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