示例#1
0
 public void AddLocals(MethodDefinition hostMethod)
 {
     _constructorArguments = hostMethod.AddLocal <List <object> >();
     _currentArgument      = hostMethod.AddLocal <object>();
     _methodContext        = hostMethod.AddLocal <ITypeActivationContext>();
     _currentActivator     = hostMethod.AddLocal <ITypeActivator>();
 }
示例#2
0
        /// <summary>
        /// Adds a prolog to the given method body.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the given method body.</param>
        public void AddProlog(CilWorker IL)
        {
            MethodDefinition method = IL.GetMethod();

            _surroundingImplementation      = method.AddLocal <IAroundInvoke>();
            _surroundingClassImplementation = method.AddLocal <IAroundInvoke>();

            Instruction      skipProlog     = IL.Create(OpCodes.Nop);
            TypeDefinition   declaringType  = method.DeclaringType;
            ModuleDefinition module         = declaringType.Module;
            TypeReference    modifiableType = module.ImportType <IModifiableType>();

            if (method.HasThis)
            {
                IL.Emit(OpCodes.Ldarg_0);
                IL.Emit(OpCodes.Isinst, modifiableType);
                IL.Emit(OpCodes.Brfalse, skipProlog);
            }

            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipProlog);

            // var provider = this.MethodReplacementProvider;

            if (_getMethodReplacementProvider != null)
            {
                _getMethodReplacementProvider.Emit(IL);
            }

            var getAroundInvokeProvider = new GetAroundInvokeProvider(_aroundInvokeProvider, _providerName);

            getAroundInvokeProvider.Emit(IL);

            // if (aroundInvokeProvider != null ) {
            Instruction skipGetSurroundingImplementation     = IL.Create(OpCodes.Nop);
            var         getSurroundingImplementationInstance = new GetSurroundingImplementationInstance(_aroundInvokeProvider,
                                                                                                        _invocationInfo,
                                                                                                        _surroundingImplementation,
                                                                                                        skipGetSurroundingImplementation);

            getSurroundingImplementationInstance.Emit(IL);

            // }

            IL.Append(skipGetSurroundingImplementation);
            var emitBeforeInvoke = new EmitBeforeInvoke(_invocationInfo, _surroundingClassImplementation,
                                                        _surroundingImplementation, _registryType);

            emitBeforeInvoke.Emit(IL);

            IL.Append(skipProlog);
        }
        /// <summary>
        /// Adds local variables to the <paramref name="hostMethod"/>.
        /// </summary>
        /// <param name="hostMethod">The target method.</param>
        public override void AddLocals(MethodDefinition hostMethod)
        {
            _exception        = hostMethod.AddLocal <Exception>();
            _invocationInfo   = hostMethod.AddLocal <IInvocationInfo>();
            _exceptionHandler = hostMethod.AddLocal <IExceptionHandler>();
            _exceptionInfo    = hostMethod.AddLocal <IExceptionHandlerInfo>();

            var returnType = hostMethod.ReturnType.ReturnType;

            if (returnType != _voidType)
            {
                _returnValue = hostMethod.AddLocal <object>();
            }
        }
示例#4
0
        /// <summary>
        /// Replaces the user code with a stub.
        /// Moves the original code to a new method
        /// </summary>
        /// <param name="td">The class containing the method </param>
        /// <param name="md">The method to be stubbed </param>
        /// <param name="ServerRpcAttr">The attribute that made this an RPC</param>
        /// <returns>The method containing the original code</returns>
        /// <remarks>
        /// Generates code like this:
        /// <code>
        /// public void MyServerRpc(float thrusting, int spin)
        /// {
        ///     NetworkWriter networkWriter = new NetworkWriter();
        ///     networkWriter.Write(thrusting);
        ///     networkWriter.WritePackedUInt32((uint) spin);
        ///     base.SendServerRpcInternal(cmdName, networkWriter, cmdName);
        /// }
        ///
        /// public void UserCode_MyServerRpc(float thrusting, int spin)
        /// {
        ///     // whatever the user was doing before
        ///
        /// }
        /// </code>
        /// </remarks>
        MethodDefinition GenerateStub(MethodDefinition md, CustomAttribute serverRpcAttr)
        {
            MethodDefinition cmd = SubstituteMethod(md);

            ILProcessor worker = md.Body.GetILProcessor();

            // NetworkWriter writer = NetworkWriterPool.GetWriter()
            VariableDefinition writer = md.AddLocal <PooledNetworkWriter>();

            worker.Append(worker.Create(OpCodes.Call, md.Module.ImportReference(() => NetworkWriterPool.GetWriter())));
            worker.Append(worker.Create(OpCodes.Stloc, writer));

            // write all the arguments that the user passed to the Cmd call
            if (!WriteArguments(worker, md, writer, RemoteCallType.ServerRpc))
            {
                return(cmd);
            }

            string cmdName = md.Name;

            int  channel          = serverRpcAttr.GetField("channel", 0);
            bool requireAuthority = serverRpcAttr.GetField("requireAuthority", true);


            // invoke internal send and return
            // load 'base.' to call the SendServerRpc function with
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldtoken, md.DeclaringType));
            // invokerClass
            worker.Append(worker.Create(OpCodes.Call, () => Type.GetTypeFromHandle(default)));
        static Instruction ProcessInstructionLoadAddress(MethodDefinition md, Instruction instr, FieldDefinition opField)
        {
            // does it set a field that we replaced?
            if (Weaver.WeaveLists.replacementSetterProperties.TryGetValue(opField, out MethodDefinition replacement))
            {
                // we have a replacement for this property
                // is the next instruction a initobj?
                Instruction nextInstr = instr.Next;

                if (nextInstr.OpCode == OpCodes.Initobj)
                {
                    // we need to replace this code with:
                    //     var tmp = new MyStruct();
                    //     this.set_Networkxxxx(tmp);
                    ILProcessor        worker      = md.Body.GetILProcessor();
                    VariableDefinition tmpVariable = md.AddLocal(opField.FieldType);

                    worker.InsertBefore(instr, worker.Create(OpCodes.Ldloca, tmpVariable));
                    worker.InsertBefore(instr, worker.Create(OpCodes.Initobj, opField.FieldType));
                    worker.InsertBefore(instr, worker.Create(OpCodes.Ldloc, tmpVariable));
                    Instruction newInstr = worker.Create(OpCodes.Call, replacement);
                    worker.InsertBefore(instr, newInstr);

                    worker.Remove(instr);
                    worker.Remove(nextInstr);

                    return(newInstr);
                }
            }

            return(instr);
        }
示例#6
0
        /// <summary>
        /// Emits the instructions that will instantiate the current implementation.
        /// </summary>
        /// <param name="dependency">The dependency that describes the service to be instantiated.</param>
        /// <param name="serviceMap">The service map that contains the list of dependencies in the application.</param>
        /// <param name="targetMethod">The target method.</param>
        public void Emit(IDependency dependency, IDictionary <IDependency, IImplementation> serviceMap, MethodDefinition targetMethod)
        {
            var declaringType = targetMethod.DeclaringType;
            var module        = declaringType.Module;

            var listType = typeof(List <>).MakeGenericType(_serviceType);
            var listCtor = module.ImportConstructor(listType, new System.Type[0]);

            var listVariable = targetMethod.AddLocal(listType);
            var IL           = targetMethod.GetILGenerator();

            IL.Emit(OpCodes.Newobj, listCtor);
            IL.Emit(OpCodes.Stloc, listVariable);

            var targetDependencies = (from d in serviceMap.Keys
                                      where d.ServiceType == _serviceType
                                      select d).ToArray();

            var addItem = module.ImportMethod("Add", listType);

            var serviceType    = module.Import(_serviceType);
            var currentService = targetMethod.AddLocal(_serviceType);

            foreach (var currentDependency in targetDependencies)
            {
                IL.Emit(OpCodes.Ldloc, listVariable);

                // Instantiate the current service type
                var implementation = new ContainerCall(currentDependency.ServiceType, currentDependency.ServiceName);
                implementation.Emit(currentDependency, serviceMap, targetMethod);

                IL.Emit(OpCodes.Isinst, serviceType);
                IL.Emit(OpCodes.Stloc, currentService);

                // Call IInitialize.Initialize(container) on the current service type
                _initializer.Initialize(IL, module, currentService);

                IL.Emit(OpCodes.Ldloc, currentService);
                IL.Emit(OpCodes.Callvirt, addItem);
            }

            var enumerableType         = typeof(IEnumerable <>).MakeGenericType(_serviceType);
            var importedEnumerableType = module.Import(enumerableType);

            IL.Emit(OpCodes.Ldloc, listVariable);
            IL.Emit(OpCodes.Isinst, importedEnumerableType);
        }
示例#7
0
        /// <summary>
        /// Replaces the user code with a stub.
        /// Moves the original code to a new method
        /// </summary>
        /// <param name="td">The class containing the method </param>
        /// <param name="md">The method to be stubbed </param>
        /// <param name="ServerRpcAttr">The attribute that made this an RPC</param>
        /// <returns>The method containing the original code</returns>
        /// <remarks>
        /// Generates code like this: (Observers case)
        /// <code>
        /// public void Test (int param)
        /// {
        ///     NetworkWriter writer = new NetworkWriter();
        ///     writer.WritePackedUInt32((uint) param);
        ///     base.SendRpcInternal(typeof(class),"RpcTest", writer, 0);
        /// }
        /// public void UserCode_Test(int param)
        /// {
        ///     // whatever the user did before
        /// }
        /// </code>
        ///
        /// Generates code like this: (Owner/Connection case)
        /// <code>
        /// public void TargetTest(NetworkConnection conn, int param)
        /// {
        ///     NetworkWriter writer = new NetworkWriter();
        ///     writer.WritePackedUInt32((uint)param);
        ///     base.SendTargetRpcInternal(conn, typeof(class), "TargetTest", val);
        /// }
        ///
        /// public void UserCode_TargetTest(NetworkConnection conn, int param)
        /// {
        ///     // whatever the user did before
        /// }
        /// </code>
        /// or if no connection is specified
        ///
        /// <code>
        /// public void TargetTest (int param)
        /// {
        ///     NetworkWriter writer = new NetworkWriter();
        ///     writer.WritePackedUInt32((uint) param);
        ///     base.SendTargetRpcInternal(null, typeof(class), "TargetTest", val);
        /// }
        ///
        /// public void UserCode_TargetTest(int param)
        /// {
        ///     // whatever the user did before
        /// }
        /// </code>
        /// </remarks>
        private MethodDefinition GenerateStub(MethodDefinition md, CustomAttribute clientRpcAttr, int rpcIndex, ValueSerializer[] paramSerializers)
        {
            var rpc = SubstituteMethod(md);

            var worker = md.Body.GetILProcessor();

            // if (IsClient)
            // {
            //    call the body
            // }
            CallBody(worker, rpc);

            // NetworkWriter writer = NetworkWriterPool.GetWriter()
            var writer = md.AddLocal <PooledNetworkWriter>();

            worker.Append(worker.Create(OpCodes.Call, () => NetworkWriterPool.GetWriter()));
            worker.Append(worker.Create(OpCodes.Stloc, writer));

            // write all the arguments that the user passed to the Rpc call
            WriteArguments(worker, md, writer, paramSerializers, RemoteCallType.ClientRpc);

            var rpcName = md.FullName;

            var target       = clientRpcAttr.GetField(nameof(ClientRpcAttribute.target), RpcTarget.Observers);
            var channel      = clientRpcAttr.GetField(nameof(ClientRpcAttribute.channel), 0);
            var excludeOwner = clientRpcAttr.GetField(nameof(ClientRpcAttribute.excludeOwner), false);

            var sendMethod = GetSendMethod(md, target);

            // ClientRpcSender.Send(this, 12345, writer, channel, requireAuthority)
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldc_I4, rpcIndex));
            worker.Append(worker.Create(OpCodes.Ldloc, writer));
            worker.Append(worker.Create(OpCodes.Ldc_I4, channel));
            // last arg of send is either bool, or NetworkPlayer
            // see ClientRpcSender.Send methods
            if (target == RpcTarget.Observers)
            {
                worker.Append(worker.Create(excludeOwner ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
            }
            else if (target == RpcTarget.Player && HasNetworkPlayerParameter(md))
            {
                worker.Append(worker.Create(OpCodes.Ldarg_1));
            }
            else // owner, or Player with no arg
            {
                worker.Append(worker.Create(OpCodes.Ldnull));
            }


            worker.Append(worker.Create(OpCodes.Call, sendMethod));

            NetworkWriterHelper.CallRelease(module, worker, writer);

            worker.Append(worker.Create(OpCodes.Ret));

            return(rpc);
        }
        private void Create_CryptGet(TypeDefinition moduleType)
        {
            var getUtf8   = ModuleDefinition.ImportReference(typeof(Encoding).GetMethod("get_UTF8", Type.EmptyTypes));
            var getString = ModuleDefinition.ImportReference(typeof(Encoding).GetMethod("GetString", new Type[] { typeof(byte[]), typeof(Int32), typeof(Int32) }));
            var lazyValue = ModuleDefinition.ImportReference(typeof(Lazy <byte[]>).GetMethod("get_Value"));
            var intern    = ModuleDefinition.ImportReference(typeof(string).GetMethod("Intern", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static));

            _cryptGetMethod = new MethodDefinition($"CryptGet_{_id}", MethodAttributes.HideBySig | MethodAttributes.Static, ModuleDefinition.ImportReference(typeof(string)));
            _cryptGetMethod.Parameters.Add(new ParameterDefinition("ndx", ParameterAttributes.None, ModuleDefinition.ImportReference(typeof(int))));
            _cryptGetMethod.Parameters.Add(new ParameterDefinition("len", ParameterAttributes.None, ModuleDefinition.ImportReference(typeof(int))));
            _cryptGetMethod.Parameters.Add(new ParameterDefinition("i", ParameterAttributes.None, ModuleDefinition.ImportReference(typeof(int))));

            AddAttrs(_cryptGetMethod.CustomAttributes);

            _cryptGetMethod.DeclaringType = moduleType;

            _cryptGetMethod.Body = new MethodBody(_cryptGetMethod);

            var il = _cryptGetMethod.Body.GetILProcessor();

            _cryptGetMethod.Body.SimplifyMacros();

            _cryptGetMethod.Body.InitLocals = true;

            _cryptGetMethod.AddLocal(typeof(string));

            var loadReturnVal = il.Create(OpCodes.Ldloc_0);

            il.Append(il.Create(OpCodes.Ldsfld, _stringsArrayField));
            il.Append(il.Create(OpCodes.Ldarg_2));
            il.Append(il.Create(OpCodes.Ldelem_Ref));
            il.Append(il.Create(OpCodes.Stloc_0));

            il.Append(il.Create(OpCodes.Ldloc_0));
            il.Append(il.Create(OpCodes.Brtrue_S, loadReturnVal));

            il.Append(il.Create(OpCodes.Call, getUtf8));
            il.Append(il.Create(OpCodes.Ldsfld, _decryptedField));
            il.Append(il.Create(OpCodes.Callvirt, lazyValue));
            il.Append(il.Create(OpCodes.Ldarg_0));
            il.Append(il.Create(OpCodes.Ldarg_1));
            il.Append(il.Create(OpCodes.Callvirt, getString));
            il.Append(il.Create(OpCodes.Call, intern));
            il.Append(il.Create(OpCodes.Stloc_0));

            il.Append(il.Create(OpCodes.Ldsfld, _stringsArrayField));
            il.Append(il.Create(OpCodes.Ldarg_2));
            il.Append(il.Create(OpCodes.Ldloc_0));
            il.Append(il.Create(OpCodes.Stelem_Ref));

            il.Append(loadReturnVal);
            il.Append(il.Create(OpCodes.Ret));

            moduleType.Methods.Add(_cryptGetMethod);

            _cryptGetMethod.Body.OptimizeMacros();
        }
示例#9
0
 // this is required to early-out from a function with a return value.
 static void InjectGuardReturnValue(MethodDefinition md, ILProcessor worker, Instruction top)
 {
     if (!md.ReturnType.Is(typeof(void)))
     {
         VariableDefinition returnLocal = md.AddLocal(md.ReturnType);
         worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, returnLocal));
         worker.InsertBefore(top, worker.Create(OpCodes.Initobj, md.ReturnType));
         worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, returnLocal));
     }
 }
示例#10
0
        /// <summary>
        /// Rewrites the instructions in the target method body.
        /// </summary>
        /// <param name="method">The target method.</param>
        /// <param name="IL">The <see cref="CilWorker"/> instance that represents the method body.</param>
        /// <param name="oldInstructions">The IL instructions of the original method body.</param>
        protected override void RewriteMethodBody(MethodDefinition method, CilWorker IL,
                                                  IEnumerable <Instruction> oldInstructions)
        {
            if (IsExcluded(method))
            {
                AddOriginalInstructions(IL, oldInstructions);
                return;
            }

            VariableDefinition interceptionDisabled      = method.AddLocal <bool>();
            VariableDefinition invocationInfo            = method.AddLocal <IInvocationInfo>();
            VariableDefinition aroundInvokeProvider      = method.AddLocal <IAroundInvokeProvider>();
            VariableDefinition methodReplacementProvider = method.AddLocal <IMethodReplacementProvider>();


            VariableDefinition returnValue = method.AddLocal <object>();
            VariableDefinition classMethodReplacementProvider = method.AddLocal <IMethodReplacementProvider>();

            Func <ModuleDefinition, MethodReference> getInstanceMethodReplacementProviderMethod =
                module => module.Import(typeof(IMethodReplacementHost).GetMethod("get_MethodBodyReplacementProvider"));

            var parameters = new MethodBodyRewriterParameters(IL,
                                                              oldInstructions,
                                                              interceptionDisabled,
                                                              invocationInfo, returnValue,
                                                              methodReplacementProvider,
                                                              aroundInvokeProvider,
                                                              classMethodReplacementProvider,
                                                              getInstanceMethodReplacementProviderMethod,
                                                              typeof(AroundMethodBodyRegistry));

            var emitter = new InvocationInfoEmitter(true);

            IInstructionEmitter getMethodReplacementProvider =
                new GetMethodReplacementProvider(methodReplacementProvider, method,
                                                 getInstanceMethodReplacementProviderMethod);

            IInstructionEmitter getInterceptionDisabled           = new GetInterceptionDisabled(parameters);
            ISurroundMethodBody surroundMethodBody                = new SurroundMethodBody(parameters, "AroundMethodBodyProvider");
            IInstructionEmitter getClassMethodReplacementProvider = new GetClassMethodReplacementProvider(parameters,
                                                                                                          module =>
                                                                                                          module.Import(
                                                                                                              typeof(
                                                                                                                  MethodBodyReplacementProviderRegistry
                                                                                                                  ).
                                                                                                              GetMethod
                                                                                                                  ("GetProvider")));
            IInstructionEmitter addMethodReplacement = new AddMethodReplacementImplementation(parameters);

            var rewriter = new InterceptAndSurroundMethodBody(emitter, getInterceptionDisabled, surroundMethodBody,
                                                              getMethodReplacementProvider,
                                                              getClassMethodReplacementProvider, addMethodReplacement,
                                                              parameters);

            // Determine whether or not the method should be intercepted
            rewriter.Rewrite(method, IL, oldInstructions);
        }
示例#11
0
        private static void DefineSerializationConstructor(ModuleDefinition module, TypeDefinition targetType)
        {
            MethodReference getTypeFromHandle = module.ImportMethod <Type>("GetTypeFromHandle",
                                                                           BindingFlags.Public | BindingFlags.Static);

            var parameterTypes = new[] { typeof(SerializationInfo), typeof(StreamingContext) };

            // Define the constructor signature
            MethodDefinition serializationCtor = targetType.AddDefaultConstructor();

            serializationCtor.AddParameters(parameterTypes);

            serializationCtor.Attributes = MethodAttributes.HideBySig | MethodAttributes.SpecialName |
                                           MethodAttributes.RTSpecialName | MethodAttributes.Public;
            TypeReference      interceptorInterfaceType = module.ImportType <IInterceptor>();
            VariableDefinition interceptorTypeVariable  = serializationCtor.AddLocal <Type>();

            MethodBody body = serializationCtor.Body;

            body.InitLocals = true;

            CilWorker IL = serializationCtor.GetILGenerator();

            IL.Emit(OpCodes.Ldtoken, interceptorInterfaceType);
            IL.Emit(OpCodes.Call, getTypeFromHandle);
            IL.Emit(OpCodes.Stloc, interceptorTypeVariable);

            MethodReference defaultConstructor = module.ImportConstructor <object>();

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Call, defaultConstructor);

            // __interceptor = (IInterceptor)info.GetValue("__interceptor", typeof(IInterceptor));
            MethodReference getValue = module.ImportMethod <SerializationInfo>("GetValue");

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Ldarg_1);
            IL.Emit(OpCodes.Ldstr, "__interceptor");
            IL.Emit(OpCodes.Ldloc, interceptorTypeVariable);
            IL.Emit(OpCodes.Callvirt, getValue);
            IL.Emit(OpCodes.Castclass, interceptorInterfaceType);

            MethodReference setInterceptor = module.ImportMethod <IProxy>("set_Interceptor");

            IL.Emit(OpCodes.Callvirt, setInterceptor);
            ;
            IL.Emit(OpCodes.Ret);
        }
示例#12
0
        /// <summary>
        /// Replaces the user code with a stub.
        /// Moves the original code to a new method
        /// </summary>
        /// <param name="td">The class containing the method </param>
        /// <param name="md">The method to be stubbed </param>
        /// <param name="ServerRpcAttr">The attribute that made this an RPC</param>
        /// <returns>The method containing the original code</returns>
        /// <remarks>
        /// Generates code like this: (Observers case)
        /// <code>
        /// public void Test (int param)
        /// {
        ///     NetworkWriter writer = new NetworkWriter();
        ///     writer.WritePackedUInt32((uint) param);
        ///     base.SendRpcInternal(typeof(class),"RpcTest", writer, 0);
        /// }
        /// public void UserCode_Test(int param)
        /// {
        ///     // whatever the user did before
        /// }
        /// </code>
        ///
        /// Generates code like this: (Owner/Connection case)
        /// <code>
        /// public void TargetTest(NetworkConnection conn, int param)
        /// {
        ///     NetworkWriter writer = new NetworkWriter();
        ///     writer.WritePackedUInt32((uint)param);
        ///     base.SendTargetRpcInternal(conn, typeof(class), "TargetTest", val);
        /// }
        ///
        /// public void UserCode_TargetTest(NetworkConnection conn, int param)
        /// {
        ///     // whatever the user did before
        /// }
        /// </code>
        /// or if no connection is specified
        ///
        /// <code>
        /// public void TargetTest (int param)
        /// {
        ///     NetworkWriter writer = new NetworkWriter();
        ///     writer.WritePackedUInt32((uint) param);
        ///     base.SendTargetRpcInternal(null, typeof(class), "TargetTest", val);
        /// }
        ///
        /// public void UserCode_TargetTest(int param)
        /// {
        ///     // whatever the user did before
        /// }
        /// </code>
        /// </remarks>
        MethodDefinition GenerateStub(MethodDefinition md, CustomAttribute clientRpcAttr)
        {
            MethodDefinition rpc = SubstituteMethod(md);

            ILProcessor worker = md.Body.GetILProcessor();

            // if (IsClient)
            // {
            //    call the body
            // }
            CallBody(worker, rpc);

            // NetworkWriter writer = NetworkWriterPool.GetWriter()
            VariableDefinition writer = md.AddLocal <PooledNetworkWriter>();

            worker.Append(worker.Create(OpCodes.Call, () => NetworkWriterPool.GetWriter()));
            worker.Append(worker.Create(OpCodes.Stloc, writer));

            // write all the arguments that the user passed to the Rpc call
            if (!WriteArguments(worker, md, writer, RemoteCallType.ClientRpc))
            {
                return(rpc);
            }

            string rpcName = md.Name;

            Client target       = clientRpcAttr.GetField("target", Client.Observers);
            int    channel      = clientRpcAttr.GetField("channel", 0);
            bool   excludeOwner = clientRpcAttr.GetField("excludeOwner", false);

            // invoke SendInternal and return
            // this
            worker.Append(worker.Create(OpCodes.Ldarg_0));

            if (target == Client.Connection && HasNetworkConnectionParameter(md))
            {
                worker.Append(worker.Create(OpCodes.Ldarg_1));
            }
            else if (target == Client.Owner)
            {
                worker.Append(worker.Create(OpCodes.Ldnull));
            }

            worker.Append(worker.Create(OpCodes.Ldtoken, md.DeclaringType.ConvertToGenericIfNeeded()));
            // invokerClass
            worker.Append(worker.Create(OpCodes.Call, () => Type.GetTypeFromHandle(default)));
示例#13
0
        /// <summary>
        /// Replaces the user code with a stub.
        /// Moves the original code to a new method
        /// </summary>
        /// <param name="td">The class containing the method </param>
        /// <param name="md">The method to be stubbed </param>
        /// <param name="ServerRpcAttr">The attribute that made this an RPC</param>
        /// <returns>The method containing the original code</returns>
        /// <remarks>
        /// Generates code like this:
        /// <code>
        /// public void MyServerRpc(float thrusting, int spin)
        /// {
        ///     NetworkWriter networkWriter = new NetworkWriter();
        ///     networkWriter.Write(thrusting);
        ///     networkWriter.WritePackedUInt32((uint) spin);
        ///     base.SendServerRpcInternal(cmdName, networkWriter, cmdName);
        /// }
        ///
        /// public void UserCode_MyServerRpc(float thrusting, int spin)
        /// {
        ///     // whatever the user was doing before
        ///
        /// }
        /// </code>
        /// </remarks>
        private MethodDefinition GenerateStub(MethodDefinition md, CustomAttribute serverRpcAttr, int rpcIndex, ValueSerializer[] paramSerializers)
        {
            var cmd = SubstituteMethod(md);

            var worker = md.Body.GetILProcessor();

            // if (IsServer)
            // {
            //    call the body
            //    return;
            // }
            CallBody(worker, cmd);

            // NetworkWriter writer = NetworkWriterPool.GetWriter()
            var writer = md.AddLocal <PooledNetworkWriter>();

            worker.Append(worker.Create(OpCodes.Call, md.Module.ImportReference(() => NetworkWriterPool.GetWriter())));
            worker.Append(worker.Create(OpCodes.Stloc, writer));

            // write all the arguments that the user passed to the Cmd call
            WriteArguments(worker, md, writer, paramSerializers, RemoteCallType.ServerRpc);

            var cmdName = md.FullName;

            var channel          = serverRpcAttr.GetField(nameof(ServerRpcAttribute.channel), 0);
            var requireAuthority = serverRpcAttr.GetField(nameof(ServerRpcAttribute.requireAuthority), true);

            var sendMethod = GetSendMethod(md, worker);

            // ServerRpcSender.Send(this, 12345, writer, channel, requireAuthority)
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldc_I4, rpcIndex));
            worker.Append(worker.Create(OpCodes.Ldloc, writer));
            worker.Append(worker.Create(OpCodes.Ldc_I4, channel));
            worker.Append(worker.Create(requireAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
            worker.Append(worker.Create(OpCodes.Call, sendMethod));

            NetworkWriterHelper.CallRelease(module, worker, writer);

            worker.Append(worker.Create(OpCodes.Ret));

            return(cmd);
        }
示例#14
0
        // this is required to early-out from a function with "ref" or "out" parameters
        static void InjectGuardParameters(MethodDefinition md, ILProcessor worker, Instruction top)
        {
            int offset = md.Resolve().IsStatic ? 0 : 1;

            for (int index = 0; index < md.Parameters.Count; index++)
            {
                ParameterDefinition param = md.Parameters[index];
                if (param.IsOut)
                {
                    TypeReference elementType = param.ParameterType.GetElementType();

                    VariableDefinition elementLocal = md.AddLocal(elementType);

                    worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, index + offset));
                    worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, elementLocal));
                    worker.InsertBefore(top, worker.Create(OpCodes.Initobj, elementType));
                    worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, elementLocal));
                    worker.InsertBefore(top, worker.Create(OpCodes.Stobj, elementType));
                }
            }
        }
示例#15
0
 /// <summary>
 /// Adds locals to the target method.
 /// </summary>
 /// <param name="hostMethod">The method to be modified</param>
 public override void AddLocals(MethodDefinition hostMethod)
 {
     _fieldContext     = hostMethod.AddLocal <IFieldInterceptionContext>("__<>FieldInterceptionContext<>__");
     _fieldInterceptor = hostMethod.AddLocal <IFieldInterceptor>("__<>FieldInterceptor<>__");
     _currentArgument  = hostMethod.AddLocal <object>("__<>CurrentArgument<>__");
 }
示例#16
0
        /// <summary>
        /// Generates a method body for the <paramref name="targetMethod"/>.
        /// </summary>
        /// <param name="originalMethod">The method currently being intercepted.</param>
        /// <param name="targetMethod">The target method that will contain the new method body.</param>
        public void Emit(MethodInfo originalMethod, MethodDefinition targetMethod)
        {
            var invocationInfo = targetMethod.AddLocal <IInvocationInfo>();

            invocationInfo.Name = "___invocationInfo___";

            // Emit the code to generate the IInvocationInfo instance
            // and save it into the invocationInfo local variable
            if (InvocationInfoEmitter != null)
            {
                InvocationInfoEmitter.Emit(originalMethod, targetMethod, invocationInfo);
            }

            var declaringType        = targetMethod.DeclaringType;
            var module               = declaringType.Module;
            var proxyType            = module.ImportType <IProxy>();
            var getInterceptorMethod = module.ImportMethod("get_Interceptor", typeof(IProxy));
            var interceptor          = targetMethod.AddLocal <IInterceptor>();
            var arguments            = targetMethod.AddLocal <object[]>();

            // if (!(this is IProxy))
            var IL = targetMethod.GetILGenerator();

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, proxyType);

            var noImplementationFound = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Brfalse, noImplementationFound);

            var endLabel = IL.Create(OpCodes.Nop);

            EmitGetInterceptorInstruction(IL, proxyType, getInterceptorMethod);
            IL.Emit(OpCodes.Stloc, interceptor);

            //If (interceptor == null)
            //    throw a not implemented exception here
            IL.Emit(OpCodes.Ldloc, interceptor);
            IL.Emit(OpCodes.Brfalse, noImplementationFound);


            // var returnValue = interceptor.Intercept(info);
            var voidType        = module.ImportType(typeof(void));
            var interceptMethod = module.ImportMethod <IInterceptor>("Intercept", typeof(IInvocationInfo));

            IL.Emit(OpCodes.Ldloc, interceptor);
            IL.Emit(OpCodes.Ldloc, invocationInfo);
            IL.Emit(OpCodes.Callvirt, interceptMethod);

            // Save the ref arguments
            var parameters = from ParameterDefinition param in targetMethod.Parameters
                             select param;

            // Determine the return type
            var returnType = targetMethod.ReturnType != null
                ? targetMethod.ReturnType.ReturnType
                : voidType;

            IL.PackageReturnValue(module, returnType);

            SaveRefArguments(IL, parameters, invocationInfo, arguments);
            IL.Emit(OpCodes.Br, endLabel);

            // This code at this point will execute if no implementation
            // is found
            IL.Append(noImplementationFound);

            ImplementNotFound(IL);

            IL.Append(endLabel);
            IL.Emit(OpCodes.Ret);
        }
示例#17
0
        public override void AddLocals(MethodDefinition hostMethod)
        {
            var body = hostMethod.Body;

            body.InitLocals = true;

            _currentArguments = hostMethod.AddLocal <Stack <object> >("__arguments");
            _currentArgument  = hostMethod.AddLocal <object>("__currentArgument");
            _parameterTypes   = hostMethod.AddLocal <Type[]>("__parameterTypes");
            _typeArguments    = hostMethod.AddLocal <Type[]>("__typeArguments");
            _invocationInfo   = hostMethod.AddLocal <IInvocationInfo>("___invocationInfo");

            _target         = hostMethod.AddLocal <object>("__target");
            _replacement    = hostMethod.AddLocal <IInterceptor>("__interceptor");
            _canReplaceFlag = hostMethod.AddLocal <bool>("__canReplace");

            _staticProvider       = hostMethod.AddLocal <IMethodReplacementProvider>("__staticProvider");
            _instanceProvider     = hostMethod.AddLocal <IMethodReplacementProvider>("__instanceProvider");
            _interceptionDisabled = hostMethod.AddLocal <bool>();

            _methodReplacementProvider = hostMethod.AddLocal <IMethodReplacementProvider>();
            _aroundInvokeProvider      = hostMethod.AddLocal <IAroundInvokeProvider>();
            _returnValue = hostMethod.AddLocal <object>();
        }
示例#18
0
 /// <summary>
 /// Adds a named <see cref="VariableDefinition">local variable</see>
 /// instance to the target <paramref name="methodDef">method definition</paramref>.
 /// </summary>
 /// <typeparam name="T">The object <see cref="System.Type">type</see> that describes the type of objects that will be stored by the local variable.</typeparam>
 /// <param name="methodDef">The <paramref name="methodDef"/> instance which will contain the local variable.</param>
 /// <param name="variableName">The name of the local variable.</param>
 /// <returns>A <see cref="VariableDefinition"/> that represents the local variable itself.</returns>
 public static VariableDefinition AddLocal <T>(this MethodDefinition methodDef, string variableName)
 {
     return(methodDef.AddLocal(variableName, typeof(T)));
 }
示例#19
0
 /// <summary>
 /// Adds a <see cref="VariableDefinition">local variable</see>
 /// instance to the target <paramref name="methodDef">method definition</paramref>.
 /// </summary>
 /// <typeparam name="T">The object <see cref="System.Type">type</see> that describes the type of objects that will be stored by the local variable.</typeparam>
 /// <param name="methodDef">The <paramref name="methodDef"/> instance which will contain the local variable.</param>
 /// <returns>A <see cref="VariableDefinition"/> that represents the local variable itself.</returns>
 public static VariableDefinition AddLocal <T>(this MethodDefinition methodDef)
 {
     return(methodDef.AddLocal(typeof(T)));
 }
示例#20
0
        protected override void WeaveOriginalTarget()
        {
            var index = method.Body.Instructions.IndexOf(instruction);

            if (index == -1)
            {
                throw new BytecodeWeavingException("Instruction not found '{0}' in method '{1}'".FormatWith(instruction, method));
            }

            var dispatcher = new MethodDefinition("Dispatcher", MethodAttributes.Static | MethodAttributes.Public,
                                                  returnType ?? Module.Import(typeof(void)));

            jpStaticClass.Methods.Add(dispatcher);

            var il = dispatcher.Body.GetILProcessor();

            il.Append(OpCodes.Nop);

            if (targetType != null)
            {
                var target = new ParameterDefinition(targetType);
                dispatcher.Parameters.Add(target);
                il.Append(OpCodes.Ldarg, target);
                if (targetType.IsValueType)
                {
                    il.Append(OpCodes.Box, targetType);
                }
            }
            else
            {
                il.Append(OpCodes.Ldnull);
            }

            var args         = dispatcher.AddLocal(typeof(object[]));
            var typeOfObject = Module.Import(typeof(object));

            il.Append(OpCodes.Ldc_I4, argTypes.Length);
            il.Append(OpCodes.Newarr, typeOfObject);
            il.Append(OpCodes.Stloc, args);

            for (var i = 0; i < argTypes.Length; i++)
            {
                var arg = new ParameterDefinition(argTypes[i]);
                dispatcher.Parameters.Add(arg);

                il.Append(OpCodes.Ldloc, args);
                il.Append(OpCodes.Ldc_I4, i);
                il.Append(OpCodes.Ldarg, arg);
                if (argTypes[i].IsValueType)
                {
                    il.Append(OpCodes.Box, argTypes[i]);
                }

                il.Append(OpCodes.Stelem_Ref);
            }

            if (!method.IsStatic)
            {
                var thisType = method.DeclaringType.MakeGenerics(JpThisGenericParams);
                var arg      = new ParameterDefinition("sac$this", ParameterAttributes.None, thisType);
                dispatcher.Parameters.Add(arg);
                il.Append(OpCodes.Ldarg, arg);
                if (thisType.IsValueType)
                {
                    il.Append(OpCodes.Box, thisType);
                }
            }
            else
            {
                il.Append(OpCodes.Ldnull);
            }

            AppendCallDispatch(il, args, jpStaticClass.MakeGenericSelf());

            if (returnsVoid)
            {
                il.Append(OpCodes.Pop);
            }
            else if (returnType.IsValueType)
            {
                il.Append(OpCodes.Unbox_Any, Module.Import(returnType));
            }

            il.Append(OpCodes.Ret);

            // Dispatcher requires extra param (ThisInstance), but previous weaver might have been here
            if (!method.IsStatic && !isPreviouslyWeaved)
            {
                method.Body.GetILProcessor().InsertBefore(instruction, Instruction.Create(OpCodes.Ldarg_0));
            }

            instruction.OpCode  = OpCodes.Call;
            instruction.Operand = dispatcher.MakeHostInstanceGeneric(GetRefThisToJpStatic());
        }
        public void Rewrite(MethodDefinition method, ModuleDefinition module)
        {
            // Ignore methods that have already been modified
            var customAttributes = method.CustomAttributes;

            if (customAttributes.Any(c => c.AttributeType == _markerAttributeType))
            {
                return;
            }

            var body = method.Body;

            body.InitLocals = true;

            var oldInstructions = body.Instructions.ToArray();

            var callInstructions = oldInstructions.Where(instruction => instruction.OpCode == OpCodes.Call ||
                                                         instruction.OpCode == OpCodes.Callvirt).ToArray();

            var constructorCalls = oldInstructions.Where(instruction => instruction.OpCode == OpCodes.Newobj).ToArray();

            // Skip the method if there are no calls to intercept
            if (callInstructions.Any() || constructorCalls.Any())
            {
                // Clear the method body if and only if there are methods
                // that need to be intercepted
                body.Instructions.Clear();

                var objectType    = module.ImportType <object>();
                var il            = body.GetILProcessor();
                var targetMethods = callInstructions.Select(instruction => instruction.Operand as MethodReference).ToArray();
                var constructors  =
                    constructorCalls.Select(instruction => instruction.Operand as MethodReference).Where(c => c.DeclaringType != objectType).ToArray();

                // Save the calling method
                il.PushMethod(method, module);
                il.Emit(OpCodes.Stloc, _callingMethod);

                // Precalculate all method call interceptors
                var provider    = method.AddLocal <IMethodCallProvider>();
                var getProvider = module.ImportMethod("GetProvider", typeof(MethodCallProviderRegistry));

                // Obtain the method call provider instance
                il.Emit(OpCodes.Call, getProvider);

                il.Emit(OpCodes.Stloc, provider);
                il.PushMethod(method, module);

                var hasMap = module.ImportMethod("ContainsMapFor", typeof(MethodCallMapRegistry),
                                                 BindingFlags.Public | BindingFlags.Static);
                il.Emit(OpCodes.Call, hasMap);
                il.Emit(OpCodes.Stloc, _hasExistingMap);

                // Instantiate the map
                var createMap = module.ImportMethod("GetMap", typeof(MethodCallMapRegistry),
                                                    BindingFlags.Public | BindingFlags.Static);

                il.PushMethod(method, module);
                il.Emit(OpCodes.Call, createMap);
                il.Emit(OpCodes.Stloc, _callMap);

                var skipCallMapConstruction = il.Create(OpCodes.Nop);

                il.Emit(OpCodes.Ldloc, _callMap);
                il.Emit(OpCodes.Brfalse, skipCallMapConstruction);

                // Reuse the existing map if possible
                il.Emit(OpCodes.Ldloc, _hasExistingMap);
                il.Emit(OpCodes.Brtrue, skipCallMapConstruction);

                il.Emit(OpCodes.Ldloc, provider);
                il.Emit(OpCodes.Brfalse, skipCallMapConstruction);

                // if (provider != null) {
                var interceptedMethods = new List <MethodReference>();
                interceptedMethods.AddRange(targetMethods);
                interceptedMethods.AddRange(constructors);

                // Store the list of intercepted methods
                var targetMethodCount = interceptedMethods.Count;
                il.Emit(OpCodes.Ldc_I4, targetMethodCount);
                il.Emit(OpCodes.Newarr, module.ImportType <MethodBase>());
                il.Emit(OpCodes.Stloc, _interceptedMethods);

                // Populate the array of intercepted methods

                for (var i = 0; i < targetMethodCount; i++)
                {
                    var currentMethod = interceptedMethods[i];
                    il.Emit(OpCodes.Ldloc, _interceptedMethods);
                    il.Emit(OpCodes.Ldc_I4, i);
                    il.PushMethod(currentMethod, module);
                    il.Emit(OpCodes.Stelem_Ref);
                }

                // Build the list of intercepted methods
                il.Emit(OpCodes.Ldloc, provider);
                il.Emit(OpCodes.Ldloc, _target);
                il.PushMethod(method, module);
                il.Emit(OpCodes.Ldloc, _interceptedMethods);
                il.Emit(OpCodes.Ldloc, _callMap);
                il.PushStackTrace(module);
                il.Emit(OpCodes.Callvirt, _addMethodCalls);

                il.Append(skipCallMapConstruction);

                foreach (var instruction in oldInstructions)
                {
                    var opCode = instruction.OpCode;
                    if (opCode == OpCodes.Newobj)
                    {
                        il.Emit(OpCodes.Newobj, _stackCtor);
                        il.Emit(OpCodes.Stloc, _currentArguments);
                        ReplaceConstructorCall(instruction, method, il);
                        continue;
                    }


                    if (opCode != OpCodes.Call && opCode != OpCodes.Callvirt)
                    {
                        il.Append(instruction);
                        continue;
                    }

                    // Create the stack that will hold the method arguments
                    il.Emit(OpCodes.Newobj, _stackCtor);
                    il.Emit(OpCodes.Stloc, _currentArguments);

                    if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt)
                    {
                        ReplaceMethodCallInstruction(instruction, method, il);
                    }
                }
            }

            // Add the attribute marker so that this method is only modified once
            customAttributes.Add(new CustomAttribute(_markerAttributeCtor));
        }
        public void AddLocals(MethodDefinition hostMethod)
        {
            _currentArguments  = hostMethod.AddLocal <Stack <object> >("__arguments");
            _currentArgument   = hostMethod.AddLocal <object>("__currentArgument");
            _invocationInfo    = hostMethod.AddLocal <IInvocationInfo>("___invocationInfo");
            _currentMethodCall = hostMethod.AddLocal <IMethodCall>("___currentMethodCall");

            _target             = hostMethod.AddLocal <object>("__target");
            _parameterTypes     = hostMethod.AddLocal <Type[]>("__parameterTypes");
            _typeArguments      = hostMethod.AddLocal <Type[]>("__typeArguments");
            _interceptedMethods = hostMethod.AddLocal <MethodBase[]>("___interceptedMethods");

            _callMap            = hostMethod.AddLocal <IMethodCallMap>();
            _hasMethodCall      = hostMethod.AddLocal <bool>();
            _currentMethod      = hostMethod.AddLocal <MethodBase>();
            _stackTrace         = hostMethod.AddLocal <StackTrace>();
            _currentArgsAsArray = hostMethod.AddLocal <object[]>();
            _hasExistingMap     = hostMethod.AddLocal <bool>();
            _callingMethod      = hostMethod.AddLocal <MethodBase>();
        }
示例#23
0
        private void FinishDecryptor()
        {
            var moduleType = _decryptMethod.DeclaringType;

            var il = _decryptMethod.Body.GetILProcessor();

            _decryptMethod.Body.InitLocals = true;
            VariableDefinition keyBytes        = _decryptMethod.AddLocal(typeof(byte[]));
            VariableDefinition aesProvider     = _decryptMethod.AddLocal(typeof(AesCryptoServiceProvider));
            VariableDefinition cryptoTransform = _decryptMethod.AddLocal(typeof(ICryptoTransform));
            VariableDefinition memStream       = _decryptMethod.AddLocal(typeof(MemoryStream));
            VariableDefinition cryptoStream    = _decryptMethod.AddLocal(typeof(CryptoStream));

            // Get references to the methods we'll be calling.
            var aesCtor          = ModuleDefinition.ImportReference(typeof(AesCryptoServiceProvider).GetConstructor(Type.EmptyTypes));
            var setPadding       = ModuleDefinition.ImportReference(typeof(SymmetricAlgorithm).GetMethod("set_Padding", new[] { typeof(PaddingMode) }));
            var fromBase64       = ModuleDefinition.ImportReference(typeof(Convert).GetMethod("FromBase64String", new[] { typeof(string) }));
            var createDecryptor  = ModuleDefinition.ImportReference(typeof(SymmetricAlgorithm).GetMethod("CreateDecryptor", new[] { typeof(byte[]), typeof(byte[]) }));
            var memStreamCtor    = ModuleDefinition.ImportReference(typeof(MemoryStream).GetConstructor(new[] { typeof(byte[]) }));
            var cryptoStreamCtor = ModuleDefinition.ImportReference(typeof(CryptoStream).GetConstructor(new[] { typeof(Stream), typeof(ICryptoTransform), typeof(CryptoStreamMode) }));
            var readStream       = ModuleDefinition.ImportReference(typeof(Stream).GetMethod("Read", new[] { typeof(byte[]), typeof(int), typeof(int) }));
            var disposeStream    = ModuleDefinition.ImportReference(typeof(Stream).GetMethod("Dispose", Type.EmptyTypes));
            var dispose          = ModuleDefinition.ImportReference(typeof(IDisposable).GetMethod("Dispose", Type.EmptyTypes));
            var disposeSymmetric = ModuleDefinition.ImportReference(typeof(SymmetricAlgorithm).GetMethod("Dispose", Type.EmptyTypes));

            il.Append(il.Create(OpCodes.Ldstr, Convert.ToBase64String(_key)));
            il.Append(il.Create(OpCodes.Call, fromBase64));
            il.Append(il.Create(OpCodes.Stloc_0));
            il.Append(il.Create(OpCodes.Newobj, aesCtor));
            il.Append(il.Create(OpCodes.Stloc_1));
            il.Append(il.Create(OpCodes.Ldloc_1));
            il.Append(il.Create(OpCodes.Ldc_I4_1));
            il.Append(il.Create(OpCodes.Callvirt, setPadding));
            il.Append(il.Create(OpCodes.Ldloc_1));
            il.Append(il.Create(OpCodes.Ldloc_0));
            il.Append(il.Create(OpCodes.Ldloc_0));
            il.Append(il.Create(OpCodes.Callvirt, createDecryptor));
            il.Append(il.Create(OpCodes.Stloc_2));
            il.Append(il.Create(OpCodes.Ldstr, _cipherBytes));
            il.Append(il.Create(OpCodes.Call, fromBase64));
            il.Append(il.Create(OpCodes.Newobj, memStreamCtor));
            il.Append(il.Create(OpCodes.Stloc_3));
            il.Append(il.Create(OpCodes.Ldloc_3));
            il.Append(il.Create(OpCodes.Ldloc_2));
            il.Append(il.Create(OpCodes.Ldc_I4_0));
            il.Append(il.Create(OpCodes.Newobj, cryptoStreamCtor));
            il.Append(il.Create(OpCodes.Stloc_S, cryptoStream));
            il.Append(il.Create(OpCodes.Ldc_I4, _byteCount));
            il.Append(il.Create(OpCodes.Newarr, ModuleDefinition.Import(typeof(byte))));
            il.Append(il.Create(OpCodes.Stsfld, _decryptedField));
            il.Append(il.Create(OpCodes.Ldloc_S, cryptoStream));
            il.Append(il.Create(OpCodes.Ldsfld, _decryptedField));
            il.Append(il.Create(OpCodes.Ldc_I4_0));
            il.Append(il.Create(OpCodes.Ldc_I4, _byteCount));
            il.Append(il.Create(OpCodes.Callvirt, readStream));
            il.Append(il.Create(OpCodes.Pop));
            il.Append(il.Create(OpCodes.Ldloc_S, cryptoStream));
            il.Append(il.Create(OpCodes.Callvirt, disposeStream));
            il.Append(il.Create(OpCodes.Ldloc_3));
            il.Append(il.Create(OpCodes.Callvirt, disposeStream));
            il.Append(il.Create(OpCodes.Ldloc_2));
            il.Append(il.Create(OpCodes.Callvirt, dispose));
            il.Append(il.Create(OpCodes.Ldloc_1));
            il.Append(il.Create(OpCodes.Callvirt, disposeSymmetric));

            il.Append(il.Create(OpCodes.Ret));
        }