最後活躍 1 month ago

Playing with Services Producer for NHibernate in C#

修訂 4e8c659c976f4d9227b02d23635212109b5cca9a

BaseService.cs 原始檔案
1using NHibernate;
2using System;
3using System.Collections.Generic;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7
8namespace DatabaseSample {
9 public class BaseService {
10 public static ISessionFactory _sessionFactory;
11 protected static ISession _session = null;
12
13 protected static ISession Session {
14 get { return _session; }
15 }
16 }
17}
EmployeeService.cs 原始檔案
1using DatabaseSample.Models;
2using System;
3using System.Collections.Generic;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7
8namespace DatabaseSample {
9 public class EmpresaService : BaseService {
10 public virtual void CriarEmpresas(int n) {
11 Console.WriteLine("CriarEmpresas({0})", n);
12 Contato c = new Contato("Lucas Teske", "[email protected]", "Test");
13
14 for (int i = 0; i < n; i++) {
15 Empresa e = new Empresa();
16 e.Nome = "TVS" + i;
17 e.Contato = c;
18 Session.Save(e);
19 }
20 }
21
22 public virtual void lerItems() {
23 Console.WriteLine("LerItems");
24 List<Contato> contatos = Session.CreateCriteria<Contato>().List<Contato>().ToList();
25
26 foreach (Contato c in contatos) {
27 Console.WriteLine("Nome: " + c.Nome);
28 }
29 }
30 }
31}
ServiceProducer.cs 原始檔案
1using NHibernate;
2using System;
3using System.Collections.Generic;
4using System.Linq;
5using System.Reflection;
6using System.Reflection.Emit;
7using System.Text;
8using System.Threading.Tasks;
9
10namespace DatabaseSample {
11 public static class ServiceProducer<T> {
12
13 public static T ProduceService() {
14 var myType = CompileResultType<T>();
15 return (T)Activator.CreateInstance(myType);
16 }
17
18 public static Type CompileResultType<T>() {
19 TypeBuilder tb = GetTypeBuilder<T>();
20 ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
21
22 return tb.CreateType();
23 }
24 private static TypeBuilder GetTypeBuilder<T>() {
25 var typeSignature = "customType_" + typeof(T).Name;
26 var an = new AssemblyName(typeSignature);
27 AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
28 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
29 TypeBuilder tb = moduleBuilder.DefineType(typeSignature
30 , TypeAttributes.Public |
31 TypeAttributes.Class |
32 TypeAttributes.AutoClass |
33 TypeAttributes.AnsiClass |
34 TypeAttributes.BeforeFieldInit |
35 TypeAttributes.AutoLayout
36 , typeof(T));
37
38 typeof(T).GetMethods().ToList().ForEach(m => {
39 MethodBuilder mbM = tb.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig,
40 m.ReturnType,
41 m.GetParameters().ToList().Select(a => a.ParameterType).ToArray());
42
43 var il = mbM.GetILGenerator();
44
45 il.DeclareLocal(typeof(ISessionFactory));
46 il.DeclareLocal(typeof(ISession));
47 il.DeclareLocal(typeof(ITransaction));
48 il.DeclareLocal(typeof(Exception));
49 if (!typeof(void).IsAssignableFrom(m.ReturnType)) {
50 il.DeclareLocal(m.ReturnType);
51 }
52
53 Label transactionNull = il.DefineLabel();
54 Label exit = il.DefineLabel();
55
56 // try {
57 il.BeginExceptionBlock();
58
59 // BaseService._session = BaseService._sessionFactory.OpenSession();
60 writeLine(il, "GettingSession");
61 il.Emit(OpCodes.Nop);
62 il.Emit(OpCodes.Ldsfld, typeof(BaseService).GetField("_sessionFactory"));
63 il.Emit(OpCodes.Stloc_0);
64
65 writeLine(il, "Session got!");
66 il.Emit(OpCodes.Ldloc_0);
67 il.Emit(OpCodes.Call, typeof(ISessionFactory).GetMethod("OpenSession", new Type[0]));
68 il.Emit(OpCodes.Stloc_1);
69
70 writeLine(il, "Saving session");
71 il.Emit(OpCodes.Ldloc_1);
72 il.Emit(OpCodes.Stsfld, typeof(BaseService).GetField("_session", BindingFlags.NonPublic | BindingFlags.Static));
73 il.Emit(OpCodes.Nop);
74
75 // transaction = BaseService._session.BeginTransaction()
76 writeLine(il, "Creating Transaction");
77 il.Emit(OpCodes.Ldsfld, typeof(BaseService).GetField("_session", BindingFlags.NonPublic | BindingFlags.Static));
78 il.Emit(OpCodes.Call, typeof(ISession).GetMethod("BeginTransaction", new Type[0]));
79 il.Emit(OpCodes.Stloc_2);
80
81
82 // base.{thismethod}({parameters})
83 writeLine(il, "Calling parent");
84 il.Emit(OpCodes.Ldarg_0);
85 UInt16 i = 1;
86 m.GetParameters().ToList().ForEach(a => {
87 il.Emit(OpCodes.Ldarg, i);
88 i++;
89 });
90
91 il.EmitCall(OpCodes.Call, m, new Type[0]);
92 if (!typeof(void).IsAssignableFrom(m.ReturnType)) {
93 il.Emit(OpCodes.Stloc, 4);
94 }
95
96 // transaction.Commit();
97 writeLine(il, "Commiting Transaction");
98 il.Emit(OpCodes.Ldloc_2);
99 il.Emit(OpCodes.Call, typeof(ITransaction).GetMethod("Commit"));
100
101 // } catch (Exception) {
102 il.BeginCatchBlock(typeof(Exception));
103 il.Emit(OpCodes.Pop);
104
105 // transaction.Commit();
106 writeLine(il, "Rolling back Transaction");
107 il.Emit(OpCodes.Ldloc_2);
108 il.Emit(OpCodes.Brfalse_S, transactionNull);
109 il.Emit(OpCodes.Ldloc_2);
110 il.Emit(OpCodes.Call, typeof(ITransaction).GetMethod("Rollback"));
111 writeLine(il, "Exception got!");
112 il.MarkLabel(transactionNull);
113 il.Emit(OpCodes.Rethrow);
114
115
116 // } finally {
117 il.BeginFinallyBlock();
118 // BaseService._session.Close();
119 writeLine(il, "Closing session");
120 il.Emit(OpCodes.Ldsfld, typeof(BaseService).GetField("_session", BindingFlags.NonPublic | BindingFlags.Static));
121 il.Emit(OpCodes.Brfalse_S, exit);
122 il.Emit(OpCodes.Ldsfld, typeof(BaseService).GetField("_session", BindingFlags.NonPublic | BindingFlags.Static));
123 il.Emit(OpCodes.Call, typeof(ISession).GetMethod("Close"));
124 il.Emit(OpCodes.Pop);
125 //}
126 il.EndExceptionBlock();
127
128 // return {returndata}
129 if (!typeof(void).IsAssignableFrom(m.ReturnType)) {
130 il.Emit(OpCodes.Ldloc, 4);
131 }
132
133 il.MarkLabel(exit);
134 il.Emit(OpCodes.Ret);
135 });
136
137 return tb;
138 }
139
140 private static void writeLine(ILGenerator il, string line) {
141 il.Emit(OpCodes.Ldstr, line);
142 il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
143 }
144 }
145}
146