private void InterceptMethods(Builder builder, IEnumerable <BuilderType> attributes) { if (!attributes.Any()) { return; } var stopwatch = Stopwatch.StartNew(); var iMethodInterceptor = new __IMethodInterceptor(builder); var asyncTaskMethodBuilder = new __AsyncTaskMethodBuilder(builder); var asyncTaskMethodBuilderGeneric = new __AsyncTaskMethodBuilder_1(builder); var syncRoot = new __ISyncRoot(builder); var task = new __Task(builder); var exception = new __Exception(builder); var methods = builder .FindMethodsByAttributes(attributes) .GroupBy(x => new MethodKey(x.Method, x.AsyncMethod)) .Select(x => new MethodBuilderInfo(x.Key, x.Select(y => new MethodBuilderInfoItem(y, iMethodInterceptor)))) .ToArray(); foreach (var method in methods) { this.LogInfo($"Implementing interceptors in method {method.Key.Method}"); var targetedMethod = method.Key.AsyncMethod == null ? method.Key.Method : method.Key.AsyncMethod; var attributedMethod = method.Key.Method; method.AddThisReferenceToAsyncMethod(); var typeInstance = method.GetAsyncMethodTypeInstace(); var interceptorField = new Field[method.Item.Length]; if (method.RequiresSyncRootField) { foreach (var ctors in targetedMethod.DeclaringType.GetRelevantConstructors()) { ctors.NewCode().Assign(method.SyncRoot).NewObj(builder.GetType(typeof(object)).Import().ParameterlessContructor).Insert(InsertionPosition.Beginning); } } targetedMethod .NewCode() .Context(x => { for (int i = 0; i < method.Item.Length; i++) { var item = method.Item[i]; var name = $"<{targetedMethod.Name}>_attrib{i}_{item.Attribute.Identification}"; interceptorField[i] = targetedMethod.DeclaringType.CreateField(targetedMethod.Modifiers.GetPrivate(), item.Interface.Type, name); x.Load(interceptorField[i]).IsNull().Then(y => { y.Assign(interceptorField[i]).NewObj(item.Attribute); if (item.HasSyncRootInterface) { y.Load(interceptorField[i]).As(syncRoot.Type).Call(syncRoot.SyncRoot, method.SyncRoot); } }); item.Attribute.Remove(); } }) .Try(x => { for (int i = 0; i < method.Item.Length; i++) { var item = method.Item[i]; x.Load(interceptorField[i]).As(item.Interface.Type).Call(item.Interface.OnEnter, attributedMethod.DeclaringType, typeInstance, attributedMethod, x.GetParametersArray()); } x.OriginalBody(); // Special case for async methods if (method.Key.AsyncMethod != null && method.Key.Method.ReturnType.Fullname == task.Type.Fullname) // Task return { var exceptionVar = x.CreateVariable(exception.Type); x.Assign(exceptionVar).Set( x.NewCode().Call(method.Key.AsyncMethod.DeclaringType.GetField("<>t__builder"), asyncTaskMethodBuilder.GetTask) .Call(task.GetException)); x.Load(exceptionVar).IsNotNull().Then(y => { for (int i = 0; i < method.Item.Length; i++) { y.Load(interceptorField[i]).Callvirt(method.Item[i].Interface.OnException, exceptionVar); } }); } else if (method.Key.AsyncMethod != null) // Task<> return { var exceptionVar = x.CreateVariable(exception.Type); var taskArgument = method.Key.Method.ReturnType.GetGenericArgument(0); x.Assign(exceptionVar).Set( x.NewCode().Call(method.Key.AsyncMethod.DeclaringType.GetField("<>t__builder"), asyncTaskMethodBuilderGeneric.GetTask.MakeGeneric(taskArgument)) .Call(task.GetException)); x.Load(exceptionVar).IsNotNull().Then(y => { for (int i = 0; i < method.Item.Length; i++) { y.Load(interceptorField[i]).Callvirt(method.Item[i].Interface.OnException, exceptionVar); } }); } }) .Catch(exception.Type, x => { if (method.Key.AsyncMethod == null) { for (int i = 0; i < method.Item.Length; i++) { x.Load(interceptorField[i]).As(method.Item[i].Interface.Type).Call(method.Item[i].Interface.OnException, x.Exception); } } x.Rethrow(); }) .Finally(x => { for (int i = 0; i < method.Item.Length; i++) { x.Load(interceptorField[i]).As(method.Item[i].Interface.Type).Call(method.Item[i].Interface.OnExit); } }) .EndTry() .Return() .Replace(); } ; stopwatch.Stop(); this.LogInfo($"Implementing method interceptors took {stopwatch.Elapsed.TotalMilliseconds}ms"); }
private void InterceptSimpleMethods(Builder builder, IEnumerable <BuilderType> attributes) { if (!attributes.Any()) { return; } using (new StopwatchLog(this, "method simple")) { var asyncTaskMethodBuilder = new __AsyncTaskMethodBuilder(); var asyncTaskMethodBuilderGeneric = new __AsyncTaskMethodBuilder_1(); var syncRoot = new __ISyncRoot(); var task = new __Task(); var exception = new __Exception(); var methods = builder .FindMethodsByAttributes(attributes) .Where(x => !x.Method.IsPropertyGetterSetter) .GroupBy(x => new MethodKey(x.Method, x.AsyncMethod)) .Select(x => new MethodBuilderInfo <MethodBuilderInfoItem <__ISimpleMethodInterceptor> >(x.Key, x.Select(y => new MethodBuilderInfoItem <__ISimpleMethodInterceptor>(y, __ISimpleMethodInterceptor.Instance)))) .OrderBy(x => x.Key.Method.DeclaringType.Fullname) .ToArray(); foreach (var method in methods) { if (method.Item == null || method.Item.Length == 0) { continue; } this.Log($"Implementing method interceptors: {method.Key.Method.DeclaringType.Name.PadRight(40, ' ')} {method.Key.Method.Name}({string.Join(", ", method.Key.Method.Parameters.Select(x => x.Name))})"); var targetedMethod = method.Key.AsyncMethod ?? method.Key.Method; var attributedMethod = method.Key.Method; var typeInstance = method.Key.Method.AsyncMethodHelper.Instance; var interceptorField = new Field[method.Item.Length]; if (method.RequiresSyncRootField) { if (method.SyncRoot.IsStatic) { targetedMethod.AsyncOriginType.CreateStaticConstructor().NewCode() .Assign(method.SyncRoot).NewObj(builder.GetType(typeof(object)).Import().ParameterlessContructor) .Insert(InsertionPosition.Beginning); } else { foreach (var ctors in targetedMethod.AsyncOriginType.GetRelevantConstructors().Where(x => x.Name == ".ctor")) { ctors.NewCode().Assign(method.SyncRoot).NewObj(builder.GetType(typeof(object)).Import().ParameterlessContructor).Insert(InsertionPosition.Beginning); } } } var coder = targetedMethod .NewCode() .Context(x => { for (int i = 0; i < method.Item.Length; i++) { var item = method.Item[i]; var name = $"<{targetedMethod.Name}>_attrib{i}_{item.Attribute.Identification}"; interceptorField[i] = targetedMethod.AsyncOriginType.CreateField(targetedMethod.Modifiers.GetPrivate(), item.Interface.ToBuilderType, name); interceptorField[i].CustomAttributes.AddNonSerializedAttribute(); x.Load(interceptorField[i]).IsNull().Then(y => { y.Assign(interceptorField[i]).NewObj(item.Attribute); if (item.HasSyncRootInterface) { y.Load(interceptorField[i]).As(__ISyncRoot.Type).Call(syncRoot.SyncRoot, method.SyncRoot); } ImplementAssignMethodAttribute(builder, method.Item[i].AssignMethodAttributeInfos, interceptorField[i], item.Attribute.Attribute.Type, x); }); x.Load(interceptorField[i]).Call(item.Interface.OnEnter, attributedMethod.OriginType, typeInstance, attributedMethod, x.GetParametersArray()); item.Attribute.Remove(); } }); var position = coder.GetFirstOrDefaultPosition(x => x.OpCode == OpCodes.Stelem_Ref); if (position == null) { coder.Insert(InsertionPosition.Beginning); } else { coder.Insert(InsertionAction.After, position); } } ; } }