最后活跃于 1 month ago

Playing with Services Producer for NHibernate in C#

修订 24b85dd940d88e71cebe2d10f3a32d962677f00c

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