Mercurial > pub > bltoolkit
view Source/TypeBuilder/Builders/ImplementInterfaceBuilder.cs @ 4:f757da6161a1
!bug 100 + 2h fixed gregression
author | cin |
---|---|
date | Sun, 24 Aug 2014 17:57:42 +0400 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
using System; using System.Reflection.Emit; namespace BLToolkit.TypeBuilder.Builders { using Reflection; class ImplementInterfaceBuilder : AbstractTypeBuilderBase { public ImplementInterfaceBuilder(Type type) { _type = type; } private readonly Type _type; public override Type[] GetInterfaces() { return new[] { _type }; } public override bool IsApplied(BuildContext context, AbstractTypeBuilderList builders) { if (context == null) throw new ArgumentNullException("context"); return context.BuildElement == BuildElement.InterfaceMethod; } protected override void BuildInterfaceMethod() { var returnIfNonZero = false; var returnIfZero = false; if (Context.ReturnValue != null) { var attrs = Context.MethodBuilder.OverriddenMethod.ReturnTypeCustomAttributes.GetCustomAttributes(true); foreach (var o in attrs) { if (o is ReturnIfNonZeroAttribute) returnIfNonZero = true; else if (o is ReturnIfZeroAttribute) returnIfZero = true; } } var interfaceType = Context.CurrentInterface; var emit = Context.MethodBuilder.Emitter; foreach (var de in Context.Fields) { var property = de.Key; var field = de.Value; if (field.FieldType.IsPrimitive || field.FieldType == typeof(string)) continue; var types = field.FieldType.GetInterfaces(); foreach (var type in types) { if (type != interfaceType.Type) continue; var im = field.FieldType.GetInterfaceMap(type); for (var j = 0; j < im.InterfaceMethods.Length; j++) { if (im.InterfaceMethods[j] == Context.MethodBuilder.OverriddenMethod) { var targetMethod = im.TargetMethods[j]; var label = new Label(); var checkNull = false; if (CallLazyInstanceInsurer(field) == false && field.FieldType.IsClass) { // Check if field is null. // checkNull = true; label = emit.DefineLabel(); emit .ldarg_0 .ldfld (field) .brfalse_s (label) ; } // this. // emit .ldarg_0 .end(); // Load the field and prepare it for interface method call if the method is private. // if (field.FieldType.IsValueType) { if (targetMethod.IsPublic) emit.ldflda (field); else emit .ldfld (field) .box (field.FieldType); } else { if (targetMethod.IsPublic) emit.ldfld (field); else emit .ldfld (field) .castclass (interfaceType); } // Check parameter attributes. // var pi = Context.MethodBuilder.OverriddenMethod.GetParameters(); for (var k = 0; k < pi.Length; k++) { var attrs = pi[k].GetCustomAttributes(true); var stop = false; foreach (var a in attrs) { // Parent - set this. // if (a is ParentAttribute) { emit .ldarg_0 .end() ; if (!TypeHelper.IsSameOrParent(pi[k].ParameterType, Context.Type)) emit .castclass (pi[k].ParameterType) ; stop = true; break; } // PropertyInfo. // if (a is PropertyInfoAttribute) { var ifb = GetPropertyInfoField(property); emit.ldsfld(ifb); stop = true; break; } } if (stop) continue; // Pass argument. // emit.ldarg ((byte)(k + 1)); } // Call the method. // if (field.FieldType.IsValueType) { if (targetMethod.IsPublic) emit.call (targetMethod); else emit.callvirt (im.InterfaceMethods[j]); } else { if (targetMethod.IsPublic) emit.callvirt (targetMethod); else emit.callvirt (im.InterfaceMethods[j]); } // Return if appropriated result. // if (Context.ReturnValue != null) { emit.stloc(Context.ReturnValue); if (returnIfNonZero) { emit .ldloc (Context.ReturnValue) .brtrue (Context.ReturnLabel); } else if (returnIfZero) { emit .ldloc (Context.ReturnValue) .brfalse (Context.ReturnLabel); } } if (checkNull) emit.MarkLabel(label); break; } } break; } } } } }