Beispiel #1
0
            public AtomGetterMethodWeaver(AtomWeaverV2 weaver, PropertyDefinition property, FieldReference atomField,
                                          AtomOptions options)
            {
                _atomField = atomField;
                _options   = options;
                _property  = property;

                _atomDebugName = weaver._generateDebugNames
                    ? $"{property.DeclaringType.FullName}::{property.Name}"
                    : null;
                _resultVariable = new VariableDefinition(property.PropertyType);

                _nullCheckEndInstruction  = Instruction.Create(OpCodes.Nop);
                _directEvalEndInstruction = Instruction.Create(OpCodes.Nop);
                _loadResultInstruction    = Instruction.Create(OpCodes.Ldloc, _resultVariable);

                var propertyType = property.PropertyType;

                _atomCreateMethod   = Helpers.MakeGenericMethod(weaver._atomCreateMethod, propertyType);
                _atomPullCtorMethod = Helpers.MakeHostInstanceGeneric(weaver._atomPullCtorMethod, propertyType);
                _tryEnterMethod     = Helpers.MakeHostInstanceGeneric(weaver._atomDirectEvalMethod, propertyType);
                _atomGetMethod      = Helpers.MakeHostInstanceGeneric(weaver._atomGetValueMethod, propertyType);

                var body = property.GetMethod.Body;

                body.InitLocals = true;
                body.Variables.Add(_resultVariable);
            }
Beispiel #2
0
        private void GenerateAtom(ILProcessor proc, TypeReference type, FieldReference field,
                                  MethodReference pullMethod, MethodReference pushMethod, Func <ILProcessor, Instruction> generate)
        {
            Instruction br;

            //load class instance onto stack
            proc.Append(proc.Create(OpCodes.Ldarg_0));

            // pop class instance and push field value
            proc.Append(proc.Create(OpCodes.Ldfld, field));

            // duplicate field value
            proc.Append(br = proc.Create(OpCodes.Dup));

            {
                // pop field value and jump if atom not null
                //worker.Append(worker.Create(OpCodes.Brtrue_S, label));  //will be inserted later

                // pop field value (now stack is empty)
                proc.Append(proc.Create(OpCodes.Pop));

                //load class instance
                proc.Append(proc.Create(OpCodes.Ldarg_0));

                //create pull delegate or null
                if (pullMethod != null)
                {
                    proc.Append(proc.Create(OpCodes.Ldarg_0));
                    proc.Append(proc.Create(OpCodes.Ldftn, pullMethod));
                    proc.Append(proc.Create(OpCodes.Newobj, Helpers.MakeHostInstanceGeneric(_atomPullCtor, type)));
                }
                else
                {
                    proc.Append(proc.Create(OpCodes.Ldnull));
                }

                //create push delegate or null
                if (pushMethod != null)
                {
                    proc.Append(proc.Create(OpCodes.Ldarg_0));
                    proc.Append(proc.Create(OpCodes.Ldftn, pushMethod));
                    proc.Append(proc.Create(OpCodes.Newobj, Helpers.MakeHostInstanceGeneric(_atomPushCtor, type)));
                }
                else
                {
                    proc.Append(proc.Create(OpCodes.Ldnull));
                }

                proc.Append(proc.Create(OpCodes.Ldc_I4_0)); //keepAlive = false
                proc.Append(proc.Create(OpCodes.Ldc_I4_0)); //requireReaction = false
                proc.Append(proc.Create(OpCodes.Ldnull));   //onActive = null
                proc.Append(proc.Create(OpCodes.Ldnull));   //onInactive = null
                proc.Append(proc.Create(OpCodes.Ldnull));   //comparer = null

                //invoke Atom.Computed(pull, push, keepAlive, requiredReaction, onActive, onInactive, comparer)
                proc.Append(proc.Create(OpCodes.Call, Helpers.MakeGenericMethod(_atomFactoryComputed, type)));

                // duplicate created Atom
                proc.Append(proc.Create(OpCodes.Dup));

                //pop created atom and save it to local variable
                proc.Append(proc.Create(OpCodes.Stloc_0));

                //pop atom and save it to class field (now stack is empty)
                proc.Append(proc.Create(OpCodes.Stfld, field));

                //load atom onto stack
                proc.Append(proc.Create(OpCodes.Ldloc_0));
            }

            //use atom
            var brTarget = generate(proc);

            proc.InsertAfter(br, proc.Create(OpCodes.Brtrue_S, brTarget));

            // return
            proc.Append(proc.Create(OpCodes.Ret));
        }