예제 #1
0
 /// <summary>Connect all links and events in simulation</summary>
 public void ConnectLinksAndEvents()
 {
     scope  = new ScopingRules();
     events = new Events(this);
     events.ConnectEvents();
     links = new Core.Links();
     links.Resolve(this);
 }
예제 #2
0
        /// <summary>
        /// Returns all models which are in scope.
        /// </summary>
        public IEnumerable <IModel> FindAllInScope()
        {
            Simulation   sim   = FindAncestor <Simulation>();
            ScopingRules scope = sim?.Scope ?? new ScopingRules();

            foreach (IModel result in scope.FindAll(this))
            {
                yield return(result);
            }
        }
예제 #3
0
파일: Apsim.cs 프로젝트: oseledets/ApsimX
        /// <summary>
        /// Locates and returns all models in scope.
        /// </summary>
        /// <param name="model">The reference model</param>
        /// <returns>The found models or an empty array if not found.</returns>
        public static List <IModel> FindAll(IModel model)
        {
            var simulation = Apsim.Parent(model, typeof(Simulation)) as Simulation;

            if (simulation == null || simulation.Scope == null)
            {
                ScopingRules scope = new ScopingRules();
                return(scope.FindAll(model).ToList());
            }
            return(simulation.Scope.FindAll(model).ToList());
        }
예제 #4
0
파일: Events.cs 프로젝트: nastaranch/ApsimX
        /// <summary>
        /// Return a list of subscribers that are in scope.
        /// </summary>
        /// <param name="relativeTo">Model to base scoping rules on.</param>
        /// <param name="cache">The model/scriber cache</param>
        /// <param name="scope">An instance of scoping rules</param>
        /// <param name="subscribers">A collection of all subscribers</param>
        private static List <Subscriber> FilterSubscribersInScope(Publisher relativeTo,
                                                                  Dictionary <IModel, List <Subscriber> > cache,
                                                                  ScopingRules scope,
                                                                  List <Events.Subscriber> subscribers)
        {
            // Try cache
            List <Subscriber> subscribersInScope;

            if (cache.TryGetValue(relativeTo.Model as IModel, out subscribersInScope))
            {
                return(subscribersInScope);
            }

            List <IModel> modelsInScope = new List <IModel>(scope.FindAll(relativeTo.Model as IModel));

            subscribersInScope = new List <Subscriber>();
            subscribersInScope = subscribers.FindAll(subscriber => modelsInScope.Contains(subscriber.Model as IModel));
            cache.Add(relativeTo.Model as IModel, subscribersInScope);
            return(subscribersInScope);
        }
예제 #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="rootNode"></param>
        /// <param name="recurse">Recurse through all child models?</param>
        /// <param name="allLinks">Unresolve all links or just the non child links?</param>
        public void Resolve(IModel rootNode, bool allLinks, bool recurse = true)
        {
            var scope = new ScopingRules();

            if (recurse)
            {
                List <IModel> allModels = new List <IModel>()
                {
                    rootNode
                };
                allModels.AddRange(Apsim.ChildrenRecursively(rootNode));
                foreach (IModel modelNode in allModels)
                {
                    if (modelNode.Enabled)
                    {
                        ResolveInternal(modelNode, scope);
                    }
                }
            }
            else
            {
                ResolveInternal(rootNode, scope);
            }
        }
예제 #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="rootNode"></param>
        /// <param name="recurse">Recurse through all child models?</param>
        /// <param name="allLinks">Unresolve all links or just the non child links?</param>
        /// <param name="throwOnFail">Should all links be considered optional?</param>
        public void Resolve(IModel rootNode, bool allLinks, bool recurse = true, bool throwOnFail = false)
        {
            var scope = new ScopingRules();

            if (recurse)
            {
                List <IModel> allModels = new List <IModel>()
                {
                    rootNode
                };
                allModels.AddRange(rootNode.FindAllDescendants());
                foreach (IModel modelNode in allModels)
                {
                    if (modelNode.Enabled)
                    {
                        ResolveInternal(modelNode, scope, throwOnFail);
                    }
                }
            }
            else
            {
                ResolveInternal(rootNode, scope, throwOnFail);
            }
        }
예제 #7
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 is ParentLinkAttribute)
                 {
                     matches = new List <object>();
                     matches.Add(GetParent(obj, fieldType));
                 }
                 else if (link is LinkByPathAttribute)
                 {
                     var    locater = new Locater();
                     object match   = locater.Get((link as LinkByPathAttribute).Path, obj as Model);
                     if (match != null)
                     {
                         matches.Add(match);
                     }
                 }
                 else if (link.IsScoped(field))
                 {
                     matches = scope.FindAll(obj as IModel).Cast <object>().ToList();
                 }
                 else
                 {
                     matches = GetChildren(obj);
                 }
             }
             matches.RemoveAll(match => !fieldType.IsAssignableFrom(GetModel(match).GetType()));
             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]);
             }
         }
     }
 }
예제 #8
0
 /// <summary>
 /// Clears the existing Scoping Rules
 /// </summary>
 public void ClearScopingRules()
 {
     scope = new ScopingRules();
 }
예제 #9
0
 /// <summary>Constructor</summary>
 public Simulation()
 {
     locater = new Locater();
     scope   = new ScopingRules();
 }
예제 #10
0
            /// <summary>Find all event subscribers in the specified models.</summary>
            /// <param name="name">The name of the event to look for</param>
            /// <param name="relativeTo">The model to use in scoping lookup</param>
            /// <param name="scope">Scoping rules</param>
            /// <returns>The list of event subscribers</returns>
            internal static List <Subscriber> FindAll(string name, IModel relativeTo, ScopingRules scope)
            {
                List <Subscriber> subscribers = new List <Subscriber>();

                foreach (IModel modelNode in scope.FindAll(relativeTo))
                {
                    foreach (MethodInfo method in modelNode.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy))
                    {
                        EventSubscribeAttribute subscriberAttribute = (EventSubscribeAttribute)ReflectionUtilities.GetAttribute(method, typeof(EventSubscribeAttribute), false);
                        if (subscriberAttribute != null && subscriberAttribute.ToString() == name)
                        {
                            subscribers.Add(new Subscriber(subscriberAttribute.ToString(), modelNode, method));
                        }
                    }
                }

                return(subscribers);
            }
예제 #11
0
            internal static Dictionary <string, List <Subscriber> > GetAll(string name, IModel relativeTo, ScopingRules scope)
            {
                IModel[] allModels = scope.FindAll(relativeTo);
                Dictionary <string, List <Subscriber> > subscribers = new Dictionary <string, List <Subscriber> >();

                foreach (IModel modelNode in allModels)
                {
                    foreach (MethodInfo method in modelNode.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy))
                    {
                        EventSubscribeAttribute attribute = (EventSubscribeAttribute)ReflectionUtilities.GetAttribute(method, typeof(EventSubscribeAttribute), false);
                        if (attribute != null)
                        {
                            string eventName = attribute.ToString();

                            if (!eventName.Equals(name, StringComparison.InvariantCultureIgnoreCase))
                            {
                                continue;
                            }

                            Subscriber subscriber = new Subscriber(eventName, modelNode, method);

                            if (subscribers[eventName] == null)
                            {
                                subscribers[eventName] = new List <Subscriber>();
                            }
                            subscribers[eventName].Add(subscriber);
                        }
                    }
                }

                return(subscribers);
            }
예제 #12
0
 /// <summary>
 /// Internal [link] resolution algorithm.
 /// </summary>
 /// <param name="obj"></param>
 /// <param name="scope">The scoping rules to use to resolve links.</param>
 /// <param name="throwOnFail">Should all links be considered optional?</param>
 private void ResolveInternal(object obj, ScopingRules scope, bool throwOnFail)
 {
     if (obj is Models.Management.RotationManager)
     {
     }
     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 = (obj as IModel).FindAncestor <Simulation>();
                 if (typeof(ILocator).IsAssignableFrom(fieldType) && parentSimulation != null)
                 {
                     matches.Add(new Locator(obj as IModel));
                 }
                 else if (typeof(IEvent).IsAssignableFrom(fieldType) && parentSimulation != null)
                 {
                     matches.Add(new Events(obj as IModel));
                 }
             }
             if (matches.Count == 0)
             {
                 if (link.Type == LinkType.Ancestor)
                 {
                     matches = new List <object>();
                     if (obj is IModel model)
                     {
                         IModel ancestor = GetParent(model, fieldType);
                         if (ancestor == null)
                         {
                             throw new Exception($"Unable to resolve link {field.Name} in model {model.FullPath}: {model.Name} has no ancestors of type {fieldType.Name}");
                         }
                         matches.Add(ancestor);
                     }
                     else
                     {
                         throw new Exception($"Unable to resolve ancestor link {field.Name} in object of type {obj.GetType()}: object is not a model");
                     }
                 }
                 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 && !throwOnFail)
             {
                 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]);
             }
         }
     }
 }