Ejemplo n.º 1
0
        /// <summary>
        /// Runs the simulation on the current thread and waits for the simulation
        /// to complete before returning to caller. Simulation is NOT cloned before
        /// running. Use instance of Runner to get more options for running a
        /// simulation or groups of simulations.
        /// </summary>
        /// <param name="cancelToken">Is cancellation pending?</param>
        public void Run(CancellationTokenSource cancelToken = null)
        {
            IsRunning = true;

            // If the cancelToken is null then give it a default one. This can happen
            // when called from the unit tests.
            if (cancelToken == null)
            {
                cancelToken = new CancellationTokenSource();
            }

            // Remove disabled models.
            RemoveDisabledModels(this);

            // If this simulation was not created from deserialisation then we need
            // to parent all child models correctly and call OnCreated for each model.
            bool hasBeenDeserialised = Children.Count > 0 && Children[0].Parent == this;

            if (!hasBeenDeserialised)
            {
                // Parent all models.
                Apsim.ParentAllChildren(this);

                // Call OnCreated in all models.
                Apsim.ChildrenRecursively(this).ForEach(m => m.OnCreated());
            }

            if (Services == null || Services.Count < 1)
            {
                var simulations = Apsim.Parent(this, typeof(Simulations)) as Simulations;
                if (simulations != null)
                {
                    Services = simulations.GetServices();
                }
                else
                {
                    Services = new List <object>();
                    IDataStore storage = Apsim.Find(this, typeof(IDataStore)) as IDataStore;
                    if (storage != null)
                    {
                        Services.Add(Apsim.Find(this, typeof(IDataStore)));
                    }
                    Services.Add(new ScriptCompiler());
                }
            }

            var links  = new Links(Services);
            var events = new Events(this);

            try
            {
                // Connect all events.
                events.ConnectEvents();

                // Resolve all links
                links.Resolve(this, true);

                // Invoke our commencing event to let all models know we're about to start.
                Commencing?.Invoke(this, new EventArgs());

                // Begin running the simulation.
                DoCommence?.Invoke(this, new CommenceArgs()
                {
                    CancelToken = cancelToken
                });
            }
            catch (Exception err)
            {
                // Exception occurred. Write error to summary.
                string errorMessage = "ERROR in file: " + FileName + Environment.NewLine +
                                      "Simulation name: " + Name + Environment.NewLine;
                errorMessage += err.ToString();

                summary?.WriteError(this, errorMessage);

                // Rethrow exception
                throw new Exception(errorMessage, err);
            }
            finally
            {
                // Signal that the simulation is complete.
                Completed?.Invoke(this, new EventArgs());

                // Disconnect our events.
                events.DisconnectEvents();

                // Unresolve all links.
                links.Unresolve(this, true);

                IsRunning = false;
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Internal [link] resolution algorithm.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="allModels">A collection of all model wrappers</param>
        private void ResolveInternal(object obj, List <ModelWrapper> allModels)
        {
            // Go looking for [Link]s
            foreach (IVariable field in GetAllDeclarations(GetModel(obj),
                                                           GetModel(obj).GetType(),
                                                           BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public))
            {
                LinkAttribute link = field.GetAttribute(typeof(LinkAttribute)) as LinkAttribute;

                if (link != null)
                {
                    // Get the field type or the array element if it is an array field.
                    Type fieldType = field.DataType;
                    if (fieldType.IsArray)
                    {
                        fieldType = fieldType.GetElementType();
                    }
                    else if (field.DataType.Name.StartsWith("List") && field.DataType.GenericTypeArguments.Length == 1)
                    {
                        fieldType = field.DataType.GenericTypeArguments[0];
                    }

                    // Try and get a match from our services first.
                    List <object> matches;
                    matches = services.FindAll(s => fieldType.IsAssignableFrom(s.GetType()));

                    // If no match on services then try other options.
                    if (matches.Count == 0 && obj is IModel)
                    {
                        Simulation parentSimulation = Apsim.Parent(obj as IModel, typeof(Simulation)) as Simulation;
                        if (fieldType.IsAssignableFrom(typeof(ILocator)) && parentSimulation != null)
                        {
                            matches.Add(new Locator(obj as IModel));
                        }
                        else if (fieldType.IsAssignableFrom(typeof(IEvent)) && parentSimulation != null)
                        {
                            matches.Add(new Events(obj as IModel));
                        }
                    }

                    // If no match on services then try other options.
                    if (matches.Count == 0)
                    {
                        // Get a list of models that could possibly match.
                        if (link is ParentLinkAttribute)
                        {
                            matches = new List <object>();
                            matches.Add(GetParent(obj, fieldType));
                        }
                        else if (link is LinkByPathAttribute)
                        {
                            object match = Apsim.Get(obj as IModel, (link as LinkByPathAttribute).Path);
                            if (match != null)
                            {
                                matches.Add(match);
                            }
                        }
                        else if (link.IsScoped(field))
                        {
                            matches = GetModelsInScope(obj, allModels);
                        }
                        else
                        {
                            matches = GetChildren(obj);
                        }
                    }

                    // Filter possible matches to those of the correct type.
                    matches.RemoveAll(match => !fieldType.IsAssignableFrom(GetModel(match).GetType()));

                    // If we should use name to match then filter matches to those with a matching name.
                    if (link.UseNameToMatch(field))
                    {
                        matches.RemoveAll(match => !StringUtilities.StringsAreEqual(GetName(match), field.Name));
                    }

                    if (field.DataType.IsArray)
                    {
                        Array array = Array.CreateInstance(fieldType, matches.Count);
                        for (int i = 0; i < matches.Count; i++)
                        {
                            array.SetValue(GetModel(matches[i]), i);
                        }
                        field.Value = array;
                    }
                    else if (field.DataType.Name.StartsWith("List") && field.DataType.GenericTypeArguments.Length == 1)
                    {
                        var   listType            = typeof(List <>);
                        var   constructedListType = listType.MakeGenericType(fieldType);
                        IList array = Activator.CreateInstance(constructedListType) as IList;
                        for (int i = 0; i < matches.Count; i++)
                        {
                            array.Add(GetModel(matches[i]));
                        }
                        field.Value = array;
                    }
                    else if (matches.Count == 0)
                    {
                        if (!link.IsOptional)
                        {
                            throw new Exception("Cannot find a match for link " + field.Name + " in model " + GetFullName(obj));
                        }
                    }
                    else if (matches.Count >= 2 && !link.IsScoped(field))
                    {
                        throw new Exception(string.Format(": Found {0} matches for link {1} in model {2} !", matches.Count, field.Name, GetFullName(obj)));
                    }
                    else
                    {
                        field.Value = GetModel(matches[0]);
                    }
                }
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Internal [link] resolution algorithm.
 /// </summary>
 /// <param name="obj"></param>
 /// <param name="scope">The scoping rules to use to resolve links.</param>
 private void ResolveInternal(object obj, ScopingRules scope)
 {
     foreach (IVariable field in GetAllDeclarations(GetModel(obj),
                                                    GetModel(obj).GetType(),
                                                    BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public,
                                                    allLinks: true))
     {
         LinkAttribute link = field.GetAttribute(typeof(LinkAttribute)) as LinkAttribute;
         if (link != null)
         {
             Type fieldType = field.DataType;
             if (fieldType.IsArray)
             {
                 fieldType = fieldType.GetElementType();
             }
             else if (field.DataType.Name.StartsWith("List") && field.DataType.GenericTypeArguments.Length == 1)
             {
                 fieldType = field.DataType.GenericTypeArguments[0];
             }
             List <object> matches;
             matches = services.FindAll(s => fieldType.IsAssignableFrom(s.GetType()));
             if (matches.Count == 0 && obj is IModel)
             {
                 Simulation parentSimulation = Apsim.Parent(obj as IModel, typeof(Simulation)) as Simulation;
                 if (fieldType.IsAssignableFrom(typeof(ILocator)) && parentSimulation != null)
                 {
                     matches.Add(new Locator(obj as IModel));
                 }
                 else if (fieldType.IsAssignableFrom(typeof(IEvent)) && parentSimulation != null)
                 {
                     matches.Add(new Events(obj as IModel));
                 }
             }
             if (matches.Count == 0)
             {
                 if (link.Type == LinkType.Ancestor)
                 {
                     matches = new List <object>();
                     matches.Add(GetParent(obj, fieldType));
                 }
                 else if (link.Type == LinkType.Path)
                 {
                     var    locater = new Locater();
                     object match   = locater.Get(link.Path, obj as Model);
                     if (match != null)
                     {
                         matches.Add(match);
                     }
                 }
                 else if (link.Type == LinkType.Scoped)
                 {
                     matches = scope.FindAll(obj as IModel).Cast <object>().ToList();
                 }
                 else
                 {
                     matches = GetChildren(obj);
                 }
             }
             matches.RemoveAll(match => !fieldType.IsAssignableFrom(GetModel(match).GetType()));
             if (link.ByName)
             {
                 matches.RemoveAll(match => !StringUtilities.StringsAreEqual(GetName(match), field.Name));
             }
             if (field.DataType.IsArray)
             {
                 Array array = Array.CreateInstance(fieldType, matches.Count);
                 for (int i = 0; i < matches.Count; i++)
                 {
                     array.SetValue(GetModel(matches[i]), i);
                 }
                 field.Value = array;
             }
             else if (field.DataType.Name.StartsWith("List") && field.DataType.GenericTypeArguments.Length == 1)
             {
                 var   listType            = typeof(List <>);
                 var   constructedListType = listType.MakeGenericType(fieldType);
                 IList array = Activator.CreateInstance(constructedListType) as IList;
                 for (int i = 0; i < matches.Count; i++)
                 {
                     array.Add(GetModel(matches[i]));
                 }
                 field.Value = array;
             }
             else if (matches.Count == 0)
             {
                 if (!link.IsOptional)
                 {
                     throw new Exception("Cannot find a match for link " + field.Name + " in model " + GetFullName(obj));
                 }
             }
             else if (matches.Count >= 2 && link.Type != LinkType.Scoped)
             {
                 throw new Exception(string.Format(": Found {0} matches for link {1} in model {2} !", matches.Count, field.Name, GetFullName(obj)));
             }
             else
             {
                 field.Value = GetModel(matches[0]);
             }
         }
     }
 }