/// <summary> /// Combine two bounday factory to include behavior of both. /// </summary> /// <param name="authority">Authority boundary factory</param> /// <param name="factory">Secondary bounday factory to fusion with authority boundary factory</param> /// <returns>Combined boundary factory with behavior of both</returns> static public Advice.Boundary.IFactory Combine(this Advice.Boundary.IFactory authority, Advice.Boundary.IFactory factory) { if (authority.GetType() == Metadata <Advice.Boundary.Factory> .Type) { return(factory); } return(new Advice.Boundary.Sequence.Factory(authority, factory)); }
internal Advice.Boundary.IFactory Decorate(MethodBase method, Advice.Boundary.IFactory boundary) { return(this.m_Decorate(method, IntPtr.Zero, boundary) as Advice.Boundary.IFactory); // if (boundary is Advice.Boundary.Sequence.Factory) // { // var _sequence = (boundary as Advice.Boundary.Sequence.Factory).Sequence; // var _array = new Advice.Boundary.IFactory[_sequence.Length + 1]; // for (var _index = 0; _index < _array.Length; _index++) { _array[_index] = _sequence[_index]; } // _array[_sequence.Length] = this.m_Decorate(method, IntPtr.Zero, boundary) as Advice.Boundary.IFactory; // return new Advice.Boundary.Sequence.Factory(_array); // } // return new Advice.Boundary.Sequence.Factory(new Advice.Boundary.IFactory[] { boundary, this.m_Decorate(method, IntPtr.Zero, boundary) as Advice.Boundary.IFactory }); }
static public Advice Boundary(this Advice.Style.IBasic basic, Advice.Boundary.IFactory factory) { //TODO missing dispose call! return(new Advice((_Method, _Pointer, _Boundary) => { if (_Boundary != null) { return _Boundary.Combine(factory); } var _type = _Method.ReturnType(); var _parameters = _Method.GetParameters(); var _signature = _Method.Signature(); var _routine = new Closure.Routine(_Pointer, _signature, _type); var _method = new DynamicMethod(string.Empty, _type, _signature, _Method.DeclaringType, true); var _body = _method.GetILGenerator(); var _boundary = _body.DeclareLocal(Metadata <Advice.IBoundary> .Type); var _backup = _body.DeclareLocal(Metadata <Exception> .Type); var _exception = _body.DeclareLocal(Metadata <Exception> .Type); _body.Emit(OpCodes.Ldsfld, Advice.Module.DefineField(Guid.NewGuid().ToString("N"), factory)); _body.Emit(OpCodes.Callvirt, Metadata <Advice.Boundary.IFactory> .Method(_Factory => _Factory.Create())); _body.Emit(OpCodes.Stloc_0); if (_Method.IsStatic) { for (var _index = 0; _index < _signature.Length; _index++) { _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldsfld, Runtime.Inventory.Parameter(_parameters[_index])); _body.Emit(OpCodes.Ldarga_S, _index); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Argument(Argument <ParameterInfo> .Value, ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_parameters[_index].ParameterType)); } _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Begin())); _body.BeginExceptionBlock(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); if (_type == Runtime.Void) { var _return = _body.DefineLabel(); var _null = _body.DefineLabel(); var _rethrow = _body.DefineLabel(); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Return())); _body.Emit(OpCodes.Leave, _return); _body.BeginCatchBlock(Metadata <Exception> .Type); _body.Emit(OpCodes.Stloc_1); _body.Emit(OpCodes.Ldloc_1); _body.Emit(OpCodes.Stloc_2); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldloca_S, 2); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Throw(ref Argument <Exception> .Value))); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Brfalse, _null); _body.Emit(OpCodes.Ldloc_1); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Beq, _rethrow); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Throw); _body.MarkLabel(_rethrow); _body.Emit(OpCodes.Rethrow); _body.MarkLabel(_null); _body.Emit(OpCodes.Leave, _return); _body.EndExceptionBlock(); _body.MarkLabel(_return); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Dispose())); _body.Emit(OpCodes.Ret); } else { var _return = _body.DefineLabel(); var _null = _body.DefineLabel(); var _rethrow = _body.DefineLabel(); _body.DeclareLocal(_type); _body.Emit(OpCodes.Stloc_3); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldloca_S, 3); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Return(ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type)); _body.Emit(OpCodes.Leave, _return); _body.BeginCatchBlock(Metadata <Exception> .Type); _body.Emit(OpCodes.Stloc_1); _body.Emit(OpCodes.Ldloc_1); _body.Emit(OpCodes.Stloc_2); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldloca_S, 2); _body.Emit(OpCodes.Ldloca_S, 3); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Throw(ref Argument <Exception> .Value, ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod()); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Brfalse, _null); _body.Emit(OpCodes.Ldloc_1); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Beq, _rethrow); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Throw); _body.MarkLabel(_rethrow); _body.Emit(OpCodes.Rethrow); _body.MarkLabel(_null); _body.Emit(OpCodes.Leave, _return); _body.EndExceptionBlock(); _body.MarkLabel(_return); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Dispose())); _body.Emit(OpCodes.Ldloc_3); _body.Emit(OpCodes.Ret); } } else { _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldarg_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Instance(Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_Method.DeclaringType)); for (var _index = 0; _index < _parameters.Length; _index++) { _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldsfld, Runtime.Inventory.Parameter(_parameters[_index])); _body.Emit(OpCodes.Ldarga_S, _index + 1); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Argument(Argument <ParameterInfo> .Value, ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_parameters[_index].ParameterType)); } _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Begin())); _body.BeginExceptionBlock(); _body.Emit(_signature, false); _body.Emit(_Pointer, _type, _signature); if (_type == Runtime.Void) { var _return = _body.DefineLabel(); var _null = _body.DefineLabel(); var _rethrow = _body.DefineLabel(); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Return())); _body.Emit(OpCodes.Leave, _return); _body.BeginCatchBlock(Metadata <Exception> .Type); _body.Emit(OpCodes.Stloc_1); _body.Emit(OpCodes.Ldloc_1); _body.Emit(OpCodes.Stloc_2); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldloca_S, 2); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Throw(ref Argument <Exception> .Value))); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Brfalse, _null); _body.Emit(OpCodes.Ldloc_1); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Beq, _rethrow); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Throw); _body.MarkLabel(_rethrow); _body.Emit(OpCodes.Rethrow); _body.MarkLabel(_null); _body.Emit(OpCodes.Leave, _return); _body.EndExceptionBlock(); _body.MarkLabel(_return); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Dispose())); _body.Emit(OpCodes.Ret); } else { var _return = _body.DefineLabel(); var _null = _body.DefineLabel(); var _rethrow = _body.DefineLabel(); _body.DeclareLocal(_type); _body.Emit(OpCodes.Stloc_3); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldloca_S, 3); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Return(ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type)); _body.Emit(OpCodes.Leave, _return); _body.BeginCatchBlock(Metadata <Exception> .Type); _body.Emit(OpCodes.Stloc_1); _body.Emit(OpCodes.Ldloc_1); _body.Emit(OpCodes.Stloc_2); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Ldloca_S, 2); _body.Emit(OpCodes.Ldloca_S, 3); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Throw(ref Argument <Exception> .Value, ref Argument <object> .Value)).GetGenericMethodDefinition().MakeGenericMethod(_type)); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Brfalse, _null); _body.Emit(OpCodes.Ldloc_1); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Beq, _rethrow); _body.Emit(OpCodes.Ldloc_2); _body.Emit(OpCodes.Throw); _body.MarkLabel(_rethrow); _body.Emit(OpCodes.Rethrow); _body.MarkLabel(_null); _body.Emit(OpCodes.Leave, _return); _body.EndExceptionBlock(); _body.MarkLabel(_return); _body.Emit(OpCodes.Ldloc_0); _body.Emit(OpCodes.Callvirt, Metadata <Advice.IBoundary> .Method(_IBoundary => _IBoundary.Dispose())); _body.Emit(OpCodes.Ldloc_3); _body.Emit(OpCodes.Ret); } } _method.Prepare(); return _method; })); }