Mercurial > pub > bltoolkit
comparison Source/TypeBuilder/Builders/AbstractTypeBuilderBase.cs @ 0:f990fcb411a9
Копия текущей версии из github
| author | cin |
|---|---|
| date | Thu, 27 Mar 2014 21:46:09 +0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:f990fcb411a9 |
|---|---|
| 1 using System; | |
| 2 using System.Collections; | |
| 3 using System.Collections.Generic; | |
| 4 using System.Diagnostics.CodeAnalysis; | |
| 5 using System.Reflection; | |
| 6 using System.Reflection.Emit; | |
| 7 using System.Diagnostics; | |
| 8 | |
| 9 using BLToolkit.Reflection; | |
| 10 using BLToolkit.Reflection.Emit; | |
| 11 | |
| 12 namespace BLToolkit.TypeBuilder.Builders | |
| 13 { | |
| 14 public abstract class AbstractTypeBuilderBase : IAbstractTypeBuilder | |
| 15 { | |
| 16 public virtual Type[] GetInterfaces() | |
| 17 { | |
| 18 return null; | |
| 19 } | |
| 20 | |
| 21 private int _id; | |
| 22 public int ID | |
| 23 { | |
| 24 get { return _id; } | |
| 25 set { _id = value; } | |
| 26 } | |
| 27 | |
| 28 private object _targetElement; | |
| 29 public object TargetElement | |
| 30 { | |
| 31 get { return _targetElement; } | |
| 32 set { _targetElement = value; } | |
| 33 } | |
| 34 | |
| 35 private BuildContext _context; | |
| 36 public BuildContext Context | |
| 37 { | |
| 38 [DebuggerStepThrough] get { return _context; } | |
| 39 [DebuggerStepThrough] set { _context = value; } | |
| 40 } | |
| 41 | |
| 42 public virtual bool IsCompatible(BuildContext context, IAbstractTypeBuilder typeBuilder) | |
| 43 { | |
| 44 return true; | |
| 45 } | |
| 46 | |
| 47 protected bool IsRelative(IAbstractTypeBuilder typeBuilder) | |
| 48 { | |
| 49 if (typeBuilder == null) throw new ArgumentNullException("typeBuilder"); | |
| 50 | |
| 51 return GetType().IsInstanceOfType(typeBuilder) || typeBuilder.GetType().IsInstanceOfType(this); | |
| 52 } | |
| 53 | |
| 54 public virtual bool IsApplied(BuildContext context, AbstractTypeBuilderList builders) | |
| 55 { | |
| 56 return false; | |
| 57 } | |
| 58 | |
| 59 public virtual int GetPriority(BuildContext context) | |
| 60 { | |
| 61 return TypeBuilderConsts.Priority.Normal; | |
| 62 } | |
| 63 | |
| 64 public virtual void Build(BuildContext context) | |
| 65 { | |
| 66 if (context == null) throw new ArgumentNullException("context"); | |
| 67 | |
| 68 Context = context; | |
| 69 | |
| 70 switch (context.Step) | |
| 71 { | |
| 72 case BuildStep.Begin: BeginMethodBuild(); return; | |
| 73 case BuildStep.End: EndMethodBuild(); return; | |
| 74 } | |
| 75 | |
| 76 switch (context.BuildElement) | |
| 77 { | |
| 78 case BuildElement.Type: | |
| 79 switch (context.Step) | |
| 80 { | |
| 81 case BuildStep.Before: BeforeBuildType(); break; | |
| 82 case BuildStep.Build: BuildType(); break; | |
| 83 case BuildStep.After: AfterBuildType(); break; | |
| 84 case BuildStep.Catch: CatchBuildType(); break; | |
| 85 case BuildStep.Finally: FinallyBuildType(); break; | |
| 86 } | |
| 87 | |
| 88 break; | |
| 89 | |
| 90 case BuildElement.AbstractGetter: | |
| 91 switch (context.Step) | |
| 92 { | |
| 93 case BuildStep.Before: BeforeBuildAbstractGetter(); break; | |
| 94 case BuildStep.Build: BuildAbstractGetter(); break; | |
| 95 case BuildStep.After: AfterBuildAbstractGetter(); break; | |
| 96 case BuildStep.Catch: CatchBuildAbstractGetter(); break; | |
| 97 case BuildStep.Finally: FinallyBuildAbstractGetter(); break; | |
| 98 } | |
| 99 | |
| 100 break; | |
| 101 | |
| 102 case BuildElement.AbstractSetter: | |
| 103 switch (context.Step) | |
| 104 { | |
| 105 case BuildStep.Before: BeforeBuildAbstractSetter(); break; | |
| 106 case BuildStep.Build: BuildAbstractSetter(); break; | |
| 107 case BuildStep.After: AfterBuildAbstractSetter(); break; | |
| 108 case BuildStep.Catch: CatchBuildAbstractSetter(); break; | |
| 109 case BuildStep.Finally: FinallyBuildAbstractSetter(); break; | |
| 110 } | |
| 111 | |
| 112 break; | |
| 113 | |
| 114 case BuildElement.AbstractMethod: | |
| 115 switch (context.Step) | |
| 116 { | |
| 117 case BuildStep.Before: BeforeBuildAbstractMethod(); break; | |
| 118 case BuildStep.Build: BuildAbstractMethod(); break; | |
| 119 case BuildStep.After: AfterBuildAbstractMethod(); break; | |
| 120 case BuildStep.Catch: CatchBuildAbstractMethod(); break; | |
| 121 case BuildStep.Finally: FinallyBuildAbstractMethod(); break; | |
| 122 } | |
| 123 | |
| 124 break; | |
| 125 | |
| 126 case BuildElement.VirtualGetter: | |
| 127 switch (context.Step) | |
| 128 { | |
| 129 case BuildStep.Before: BeforeBuildVirtualGetter(); break; | |
| 130 case BuildStep.Build: BuildVirtualGetter(); break; | |
| 131 case BuildStep.After: AfterBuildVirtualGetter(); break; | |
| 132 case BuildStep.Catch: CatchBuildVirtualGetter(); break; | |
| 133 case BuildStep.Finally: FinallyBuildVirtualGetter(); break; | |
| 134 } | |
| 135 | |
| 136 break; | |
| 137 | |
| 138 case BuildElement.VirtualSetter: | |
| 139 switch (context.Step) | |
| 140 { | |
| 141 case BuildStep.Before: BeforeBuildVirtualSetter(); break; | |
| 142 case BuildStep.Build: BuildVirtualSetter(); break; | |
| 143 case BuildStep.After: AfterBuildVirtualSetter(); break; | |
| 144 case BuildStep.Catch: CatchBuildVirtualSetter(); break; | |
| 145 case BuildStep.Finally: FinallyBuildVirtualSetter(); break; | |
| 146 } | |
| 147 | |
| 148 break; | |
| 149 | |
| 150 case BuildElement.VirtualMethod: | |
| 151 switch (context.Step) | |
| 152 { | |
| 153 case BuildStep.Before: BeforeBuildVirtualMethod(); break; | |
| 154 case BuildStep.Build: BuildVirtualMethod(); break; | |
| 155 case BuildStep.After: AfterBuildVirtualMethod(); break; | |
| 156 case BuildStep.Catch: CatchBuildVirtualMethod(); break; | |
| 157 case BuildStep.Finally: FinallyBuildVirtualMethod(); break; | |
| 158 } | |
| 159 | |
| 160 break; | |
| 161 | |
| 162 case BuildElement.InterfaceMethod: | |
| 163 BuildInterfaceMethod(); | |
| 164 break; | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 protected virtual void BeforeBuildType () {} | |
| 169 protected virtual void BuildType () {} | |
| 170 protected virtual void AfterBuildType () {} | |
| 171 protected virtual void CatchBuildType () {} | |
| 172 protected virtual void FinallyBuildType () {} | |
| 173 | |
| 174 protected virtual void BeforeBuildAbstractGetter() {} | |
| 175 protected virtual void BuildAbstractGetter() {} | |
| 176 protected virtual void AfterBuildAbstractGetter() {} | |
| 177 protected virtual void CatchBuildAbstractGetter() {} | |
| 178 protected virtual void FinallyBuildAbstractGetter() {} | |
| 179 | |
| 180 protected virtual void BeforeBuildAbstractSetter() {} | |
| 181 protected virtual void BuildAbstractSetter() {} | |
| 182 protected virtual void AfterBuildAbstractSetter() {} | |
| 183 protected virtual void CatchBuildAbstractSetter() {} | |
| 184 protected virtual void FinallyBuildAbstractSetter() {} | |
| 185 | |
| 186 protected virtual void BeforeBuildAbstractMethod() {} | |
| 187 protected virtual void BuildAbstractMethod() {} | |
| 188 protected virtual void AfterBuildAbstractMethod() {} | |
| 189 protected virtual void CatchBuildAbstractMethod() {} | |
| 190 protected virtual void FinallyBuildAbstractMethod() {} | |
| 191 | |
| 192 protected virtual void BeforeBuildVirtualGetter () {} | |
| 193 protected virtual void BuildVirtualGetter () {} | |
| 194 protected virtual void AfterBuildVirtualGetter () {} | |
| 195 protected virtual void CatchBuildVirtualGetter () {} | |
| 196 protected virtual void FinallyBuildVirtualGetter () {} | |
| 197 | |
| 198 protected virtual void BeforeBuildVirtualSetter () {} | |
| 199 protected virtual void BuildVirtualSetter () {} | |
| 200 protected virtual void AfterBuildVirtualSetter () {} | |
| 201 protected virtual void CatchBuildVirtualSetter () {} | |
| 202 protected virtual void FinallyBuildVirtualSetter () {} | |
| 203 | |
| 204 protected virtual void BeforeBuildVirtualMethod () {} | |
| 205 protected virtual void BuildVirtualMethod () {} | |
| 206 protected virtual void AfterBuildVirtualMethod () {} | |
| 207 protected virtual void CatchBuildVirtualMethod () {} | |
| 208 protected virtual void FinallyBuildVirtualMethod () {} | |
| 209 | |
| 210 protected virtual void BuildInterfaceMethod () {} | |
| 211 | |
| 212 protected virtual void BeginMethodBuild () {} | |
| 213 protected virtual void EndMethodBuild () {} | |
| 214 | |
| 215 #region Helpers | |
| 216 | |
| 217 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] | |
| 218 protected bool CallLazyInstanceInsurer(FieldBuilder field) | |
| 219 { | |
| 220 if (field == null) throw new ArgumentNullException("field"); | |
| 221 | |
| 222 MethodBuilderHelper ensurer = Context.GetFieldInstanceEnsurer(field.Name); | |
| 223 | |
| 224 if (ensurer != null) | |
| 225 { | |
| 226 Context.MethodBuilder.Emitter | |
| 227 .ldarg_0 | |
| 228 .call (ensurer); | |
| 229 } | |
| 230 | |
| 231 return ensurer != null; | |
| 232 } | |
| 233 | |
| 234 [SuppressMessage("Microsoft.Performance", "CA1818:DoNotConcatenateStringsInsideLoops")] | |
| 235 protected virtual string GetFieldName(PropertyInfo propertyInfo) | |
| 236 { | |
| 237 string name = propertyInfo.Name; | |
| 238 | |
| 239 if (char.IsUpper(name[0]) && name.Length > 1 && char.IsLower(name[1])) | |
| 240 name = char.ToLower(name[0]) + name.Substring(1, name.Length - 1); | |
| 241 | |
| 242 name = "_" + name; | |
| 243 | |
| 244 foreach (ParameterInfo p in propertyInfo.GetIndexParameters()) | |
| 245 name += "." + p.ParameterType.FullName;//.Replace(".", "_").Replace("+", "_"); | |
| 246 | |
| 247 return name; | |
| 248 } | |
| 249 | |
| 250 protected string GetFieldName() | |
| 251 { | |
| 252 return GetFieldName(Context.CurrentProperty); | |
| 253 } | |
| 254 | |
| 255 protected FieldBuilder GetPropertyInfoField(PropertyInfo property) | |
| 256 { | |
| 257 string fieldName = GetFieldName(property) + "_$propertyInfo"; | |
| 258 FieldBuilder field = Context.GetField(fieldName); | |
| 259 | |
| 260 if (field == null) | |
| 261 { | |
| 262 field = Context.CreatePrivateStaticField(fieldName, typeof(PropertyInfo)); | |
| 263 | |
| 264 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter; | |
| 265 | |
| 266 ParameterInfo[] index = property.GetIndexParameters(); | |
| 267 | |
| 268 emit | |
| 269 .LoadType (Context.Type) | |
| 270 .ldstr (property.Name) | |
| 271 .LoadType (property.PropertyType) | |
| 272 ; | |
| 273 | |
| 274 if (index.Length == 0) | |
| 275 { | |
| 276 emit | |
| 277 .ldsfld (typeof(Type).GetField("EmptyTypes")) | |
| 278 ; | |
| 279 } | |
| 280 else | |
| 281 { | |
| 282 emit | |
| 283 .ldc_i4 (index.Length) | |
| 284 .newarr (typeof(Type)) | |
| 285 ; | |
| 286 | |
| 287 for (int i = 0; i < index.Length; i++) | |
| 288 emit | |
| 289 .dup | |
| 290 .ldc_i4 (i) | |
| 291 .LoadType (index[i].ParameterType) | |
| 292 .stelem_ref | |
| 293 .end() | |
| 294 ; | |
| 295 } | |
| 296 | |
| 297 emit | |
| 298 .call (typeof(TypeHelper).GetMethod("GetPropertyInfo")) | |
| 299 .stsfld (field) | |
| 300 ; | |
| 301 } | |
| 302 | |
| 303 return field; | |
| 304 } | |
| 305 | |
| 306 protected FieldBuilder GetPropertyInfoField() | |
| 307 { | |
| 308 return GetPropertyInfoField(Context.CurrentProperty); | |
| 309 } | |
| 310 | |
| 311 protected FieldBuilder GetParameterField() | |
| 312 { | |
| 313 string fieldName = GetFieldName() + "_$parameters"; | |
| 314 FieldBuilder field = Context.GetField(fieldName); | |
| 315 | |
| 316 if (field == null) | |
| 317 { | |
| 318 field = Context.CreatePrivateStaticField(fieldName, typeof(object[])); | |
| 319 | |
| 320 FieldBuilder piField = GetPropertyInfoField(); | |
| 321 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter; | |
| 322 | |
| 323 emit | |
| 324 .ldsfld (piField) | |
| 325 .call (typeof(TypeHelper).GetMethod("GetPropertyParameters")) | |
| 326 .stsfld (field) | |
| 327 ; | |
| 328 } | |
| 329 | |
| 330 return field; | |
| 331 } | |
| 332 | |
| 333 protected FieldBuilder GetTypeAccessorField() | |
| 334 { | |
| 335 string fieldName = "_" + GetObjectType().FullName + "_$typeAccessor"; | |
| 336 FieldBuilder field = Context.GetField(fieldName); | |
| 337 | |
| 338 if (field == null) | |
| 339 { | |
| 340 field = Context.CreatePrivateStaticField(fieldName, typeof(TypeAccessor)); | |
| 341 | |
| 342 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter; | |
| 343 | |
| 344 emit | |
| 345 .LoadType (GetObjectType()) | |
| 346 .call (typeof(TypeAccessor), "GetAccessor", typeof(Type)) | |
| 347 .stsfld (field) | |
| 348 ; | |
| 349 } | |
| 350 | |
| 351 return field; | |
| 352 } | |
| 353 | |
| 354 protected FieldBuilder GetArrayInitializer(Type arrayType) | |
| 355 { | |
| 356 string fieldName = "_array_of_$_" + arrayType.FullName; | |
| 357 FieldBuilder field = Context.GetField(fieldName); | |
| 358 | |
| 359 if (field == null) | |
| 360 { | |
| 361 field = Context.CreatePrivateStaticField(fieldName, arrayType); | |
| 362 | |
| 363 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter; | |
| 364 | |
| 365 int rank = arrayType.GetArrayRank(); | |
| 366 | |
| 367 if (rank > 1) | |
| 368 { | |
| 369 Type[] parameters = new Type[rank]; | |
| 370 | |
| 371 for (int i = 0; i < parameters.Length; i++) | |
| 372 { | |
| 373 parameters[i] = typeof(int); | |
| 374 emit.ldc_i4_0.end(); | |
| 375 } | |
| 376 | |
| 377 ConstructorInfo ci = TypeHelper.GetConstructor(arrayType, parameters); | |
| 378 | |
| 379 emit | |
| 380 .newobj (ci) | |
| 381 .stsfld (field) | |
| 382 ; | |
| 383 } | |
| 384 else | |
| 385 { | |
| 386 emit | |
| 387 .ldc_i4_0 | |
| 388 .newarr (arrayType.GetElementType()) | |
| 389 .stsfld (field) | |
| 390 ; | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 return field; | |
| 395 } | |
| 396 | |
| 397 protected FieldBuilder GetArrayInitializer() | |
| 398 { | |
| 399 return GetArrayInitializer(Context.CurrentProperty.PropertyType); | |
| 400 } | |
| 401 | |
| 402 protected virtual Type GetFieldType() | |
| 403 { | |
| 404 var pi = Context.CurrentProperty; | |
| 405 var index = pi.GetIndexParameters(); | |
| 406 | |
| 407 switch (index.Length) | |
| 408 { | |
| 409 case 0: return pi.PropertyType; | |
| 410 case 1: return typeof(Dictionary<object,object>); | |
| 411 default: | |
| 412 throw new InvalidOperationException(); | |
| 413 } | |
| 414 } | |
| 415 | |
| 416 protected virtual Type GetObjectType() | |
| 417 { | |
| 418 return GetFieldType(); | |
| 419 } | |
| 420 | |
| 421 protected virtual bool IsObjectHolder | |
| 422 { | |
| 423 get { return false; } | |
| 424 } | |
| 425 | |
| 426 #endregion | |
| 427 } | |
| 428 } |
