示例#1
0
        /// <summary>
        /// Return all fields. The normal .NET reflection doesn't return private fields in base classes.
        /// This function does.
        /// </summary>
        public static List <IVariable> GetAllDeclarations(object obj, Type type, BindingFlags flags)
        {
            if (type == typeof(Object) || type == typeof(Model))
            {
                return(new List <IVariable>());
            }

            var list = GetAllDeclarations(obj, type.BaseType, flags);

            // in order to avoid duplicates, force BindingFlags.DeclaredOnly
            foreach (FieldInfo field in type.GetFields(flags | BindingFlags.DeclaredOnly))
            {
                foreach (Attribute a in field.GetCustomAttributes())
                {
                    LinkAttribute link = a as LinkAttribute;
                    if (a != null)
                    {
                        list.Add(new VariableField(obj, field));
                    }
                }
            }
            foreach (PropertyInfo property in type.GetProperties(flags | BindingFlags.DeclaredOnly))
            {
                foreach (Attribute a in property.GetCustomAttributes())
                {
                    LinkAttribute link = a as LinkAttribute;
                    if (a != null)
                    {
                        list.Add(new VariableProperty(obj, property));
                    }
                }
            }

            return(list);
        }
示例#2
0
文件: Apsim.cs 项目: kiwiroy/ApsimX
 /// <summary>
 /// Set to null all link fields in the specified model.
 /// </summary>
 /// <param name="model">The model to look through for links</param>
 public static void UnresolveLinks(IModel model)
 {
     // Go looking for private [Link]s
     foreach (FieldInfo field in ReflectionUtilities.GetAllFields(
                  model.GetType(),
                  BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public))
     {
         LinkAttribute link = ReflectionUtilities.GetAttribute(field, typeof(LinkAttribute), false) as LinkAttribute;
         if (link != null)
         {
             field.SetValue(model, null);
         }
     }
 }
示例#3
0
        /// <summary>
        /// Go looking for a link attribute.
        /// </summary>
        /// <param name="field">The associated field.</param>
        /// <returns>Returns link or null if none field on specified field.</returns>
        private static LinkAttribute GetLinkAttribute(FieldInfo field)
        {
            var attributes = field.GetCustomAttributes();

            foreach (Attribute attribute in attributes)
            {
                LinkAttribute link = attribute as LinkAttribute;
                if (link != null)
                {
                    return(link);
                }
            }
            return(null);
        }
示例#4
0
 /// <summary>
 /// Set to null all link fields in the specified model.
 /// </summary>
 /// <param name="model">The model to look through for links</param>
 public void Unresolve(IModel model)
 {
     foreach (IModel modelNode in Apsim.ChildrenRecursively(model))
     {
         // Go looking for private [Link]s
         foreach (IVariable declaration in GetAllDeclarations(model,
                                                              model.GetType(),
                                                              BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public))
         {
             LinkAttribute link = declaration.GetAttribute(typeof(LinkAttribute)) as LinkAttribute;
             if (link != null)
             {
                 declaration.Value = null;
             }
         }
     }
 }
示例#5
0
        /// <summary>
        /// Resolve links in an unknown object e.g. user interface presenter
        /// </summary>
        /// <param name="obj"></param>
        public void Resolve(object obj)
        {
            // Go looking for [Link]s
            foreach (IVariable field in GetAllDeclarations(obj, GetModel(obj).GetType(),
                                                           BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public))
            {
                LinkAttribute link = field.GetAttribute(typeof(LinkAttribute)) as LinkAttribute;

                if (link != null)
                {
                    // For now only try matching on a service
                    object match = services.Find(s => field.DataType.IsAssignableFrom(s.GetType()));
                    if (match != null)
                    {
                        field.Value = GetModel(match);
                    }
                    else if (!link.IsOptional)
                    {
                        throw new Exception("Cannot find a match for link " + field.Name + " in model " + GetFullName(obj));
                    }
                }
            }
        }
示例#6
0
        /// <summary>
        /// Set to null all link fields in the specified model.
        /// </summary>
        /// <param name="model">The model to look through for links</param>
        /// <param name="allLinks">Unresolve all links or just the non child links?</param>
        public void Unresolve(IModel model, bool allLinks)
        {
            List <IModel> allModels = new List <IModel>()
            {
                model
            };

            allModels.AddRange(Apsim.ChildrenRecursively(model));
            foreach (IModel modelNode in allModels)
            {
                // Go looking for private [Link]s
                foreach (IVariable declaration in GetAllDeclarations(modelNode,
                                                                     modelNode.GetType(),
                                                                     BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public,
                                                                     allLinks))
                {
                    LinkAttribute link = declaration.GetAttribute(typeof(LinkAttribute)) as LinkAttribute;
                    if (link != null)
                    {
                        declaration.Value = null;
                    }
                }
            }
        }
示例#7
0
        /// <summary>
        /// Resolve links in an unknown object e.g. user interface presenter
        /// </summary>
        /// <param name="obj"></param>
        public void Resolve(object obj)
        {
            // Go looking for [Link]s
            foreach (FieldInfo field in ReflectionUtilities.GetAllFields(
                         GetModel(obj).GetType(),
                         BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public))
            {
                LinkAttribute link = GetLinkAttribute(field);

                if (link != null)
                {
                    // For now only try matching on a service
                    object match = services.Find(s => field.FieldType.IsAssignableFrom(s.GetType()));
                    if (match != null)
                    {
                        field.SetValue(GetModel(obj), GetModel(match));
                    }
                    else if (!link.IsOptional)
                    {
                        throw new Exception("Cannot find a match for link " + field.Name + " in model " + GetFullName(obj));
                    }
                }
            }
        }
示例#8
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]);
             }
         }
     }
 }
示例#9
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 (FieldInfo field in ReflectionUtilities.GetAllFields(
                         GetModel(obj).GetType(),
                         BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public))
            {
                LinkAttribute link = GetLinkAttribute(field);

                if (link != null)
                {
                    // Get the field type or the array element if it is an array field.
                    Type fieldType = field.FieldType;
                    if (fieldType.IsArray)
                    {
                        fieldType = fieldType.GetElementType();
                    }
                    else if (field.FieldType.Name.StartsWith("List") && field.FieldType.GenericTypeArguments.Length == 1)
                    {
                        fieldType = field.FieldType.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.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.FieldType.IsArray)
                    {
                        Array array = Array.CreateInstance(fieldType, matches.Count);
                        for (int i = 0; i < matches.Count; i++)
                        {
                            array.SetValue(GetModel(matches[i]), i);
                        }
                        field.SetValue(GetModel(obj), array);
                    }
                    else if (field.FieldType.Name.StartsWith("List") && field.FieldType.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.SetValue(GetModel(obj), 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.SetValue(GetModel(obj), GetModel(matches[0]));
                    }
                }
            }
        }
示例#10
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]);
             }
         }
     }
 }