Beispiel #1
0
        //TODO: Move to separate file
        /// <summary>
        /// Adds a list of Declarations to the valuestore and initializes them.
        /// The initialization is done by compiling a function that initializes the variables with
        /// the same Function calls the user used.
        /// </summary>
        /// <param name="declarations"></param>
        internal static void AddDeclarations(ISession session, IList<Declaration> declarations)
        {
            //start with a ; so when we later try to add return to the front we will get return;
            //inside a object() function, which will throw a compiler error. We want this behaviour as we dont want to
            //get a return i = 0. This would result in no compiler error thus leaving the function at the very first 
            //assignment when invoked and thus resulting in unwanted behaviour.
            string source = ";\r\n";

            //Next Add all our Variables we want to declare. By now they are in the Valuestore but dont have a value yet.
            //we now call Code that assigns them their values as specified by the user.
            foreach (Declaration decl in declarations)
            {
                object obj = new object();

                session.AddVariable(decl.Name,
                    new ValuePointer(() => obj, (o) => obj = o, decl.Type, decl.IsDynamic));

                source += String.Format("{0} = {1};\r\n", decl.Name, decl.InitializationString);
            }

            //Now we build the Assembly and call the method to initialize the variables

            CompilerResults results = AssemblyGenerator.Build(session.NewRequest(source));
            if (!results.Errors.HasErrors) //Check if we have encountered errors during Compilation
            {
                Type wrapperClass = results.CompiledAssembly.GetType("Wrapper"); //get a Reference to the Wrapper class
                MethodInfo evalMethod = wrapperClass.GetMethod("Eval", BindingFlags.Static | BindingFlags.Public); //Look for the Eval Method
                try
                {
                    //Now we call the method. since we dont ever use any console calls herer we can pass null for out and err textwriters
                    //we also surround with a try catch as we always expect a NoReturnException here. 
                    //the rest of the code will be handled in the catch.
                    evalMethod.Invoke(null, new object[] { null, null });
                }
                catch (TargetInvocationException ex)
                {

                    if (!(ex.InnerException is DebugUtilsV2.Exceptions.NoReturnException)) //trigger remove of values if we encountered an unexpected exception. because if we do, the users initializations were bad
                    {
                        RemoveDeclarationsFromValueStore(session, declarations);
                        throw; //rethrow error as it is unexpected 
                    }
                    else //we got the noreturn error, which we expected. now we lock the type of vars
                    {
                        foreach (Declaration decl in declarations)
                        {
                            if (decl.Type == null && !decl.IsDynamic) //check for vars. those will now get locked in their type
                            {
                                session.VariableStore[decl.Name].UpdateToCurrentType();
                            }
                        }
                    }
                    //Notify the session of our new items
                    session.NotifyChanged(declarations.Select(decl => decl.Name));
                }
            }
            else
            {
                RemoveDeclarationsFromValueStore(session, declarations);
            }
        }