Exemplo n.º 1
0
        private ResourceDep FilterProps(IResource o, IMemberData pi)
        {
            var behavior = ResourceOpenBehavior.Before;
            var attr     = pi.GetAttribute <ResourceOpenAttribute>();

            if (attr != null)
            {
                behavior = attr.Behavior;
            }

            return(new ResourceDep(behavior, o, pi));
        }
Exemplo n.º 2
0
        public EmbeddedMemberData(IMemberData ownerMember, IMemberData innerMember)
        {
            this.ownerMember = ownerMember;
            this.innerMember = innerMember;
            var embed = ownerMember.GetAttribute <EmbedPropertiesAttribute>();

            if (embed.PrefixPropertyName)
            {
                var prefix_name = embed.Prefix ?? ownerMember.Name;
                Name = prefix_name + "." + this.innerMember.Name;
            }
            else
            {
                Name = this.innerMember.Name;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Loads and transform the list of attributes.
        /// Some attributes are sensitive to naming, the known ones are AvailableValuesAttribute,
        /// SuggestedValueAttribute, and EnabledIf. Others might exist, but they are, for now, not supported.
        /// When NoPrefix is set on EmbedProperties, then there is no issue, but with the prefix, those names also needs
        /// to be transformed.
        /// Additionally, there is some special behavior wanted for Display, for usability and to avoid name clashing:
        ///   - If a Display name/group is set on the owner property, that should turn into a group for the embedded properties.
        ///   - If there is no display name, use the prefix name for the group.
        ///   - If there is no prefix name, don't touch DisplayAttribute.
        /// </summary>
        object[] loadAndTransformAttributes()
        {
            string prefix_name = null;

            var list = innerMember.Attributes.ToList();

            var embed = ownerMember.GetAttribute <EmbedPropertiesAttribute>();

            if (embed.PrefixPropertyName)
            {
                prefix_name = embed.Prefix ?? ownerMember.Name;
            }

            string[] pre_group1;
            string   pre_name;
            double   ownerOrder = -10000;
            bool     collapsed  = false;
            {
                var owner_display = ownerMember.GetAttribute <DisplayAttribute>();

                if (owner_display == null)
                {
                    owner_display = new DisplayAttribute(embed.PrefixPropertyName ? ownerMember.Name : "");
                    pre_group1    = owner_display.Group;
                    pre_name      = owner_display.Name;
                }
                else
                {
                    collapsed  = owner_display.Collapsed;
                    ownerOrder = owner_display.Order;
                    pre_group1 = owner_display.Group;
                    pre_name   = owner_display.Name;
                }
            }

            string name;

            string[] post_group;
            var      d = list.OfType <DisplayAttribute>().FirstOrDefault();

            if (d != null)
            {
                list.Remove(d); // need to re-add a new DisplayAttribute.
                name       = d.Name;
                post_group = d.Group;
                if (d.Collapsed)
                {
                    collapsed = true;
                }
            }
            else
            {
                name       = Name;
                post_group = Array.Empty <string>();
            }

            var groups = pre_group1.Concat(pre_name == null ? Array.Empty <string>() : new[] { pre_name }).Concat(post_group)
                         .ToArray();


            double order = -10000;

            {
                // calculate order:
                // if owner order is set, add it to the display order.
                if (d != null && d.Order != -10000.0)
                {
                    order = d.Order;
                    if (ownerOrder != -10000.0)
                    {
                        // if an order is specified, add the two orders together.
                        // this makes sure that property groups can be arranged.
                        order += ownerOrder;
                    }
                }
                else
                {
                    order = ownerOrder;
                }
            }
            d = new DisplayAttribute(name, Groups: groups,
                                     Description: d?.Description, Order: order, Collapsed: collapsed);

            list.Add(d);

            if (prefix_name != null)
            {
                // Transform properties that has issues with embedding.
                for (var i = 0; i < list.Count; i++)
                {
                    var item = list[i];
                    if (item is AvailableValuesAttribute avail)
                    {
                        list[i] = new AvailableValuesAttribute(prefix_name + "." + avail.PropertyName);
                    }
                    else if (item is SuggestedValuesAttribute sug)
                    {
                        list[i] = new SuggestedValuesAttribute(prefix_name + "." + sug.PropertyName);
                    }
                    else if (item is EnabledIfAttribute enabled)
                    {
                        list[i] = new EnabledIfAttribute(prefix_name + "." + enabled.PropertyName, enabled.PropertyValues)
                        {
                            HideIfDisabled = enabled.HideIfDisabled
                        };
                    }
                }
            }

            return(attributes = list.ToArray());
        }
Exemplo n.º 4
0
        /// <summary>
        /// Calls the PromptForDutMetadata delegate for all referenced DUTs.
        /// </summary>
        internal void StartResourcePromptAsync(TestPlanRun planRun, IEnumerable <IResource> _resources)
        {
            var resources = _resources.Where(x => x != null).ToArray();

            List <Type> componentSettingsWithMetaData = new List <Type>();
            var         componentSettings             = PluginManager.GetPlugins <ComponentSettings>();
            bool        AnyMetaData = false;

            planRun.PromptWaitHandle.Reset();

            try
            {
                foreach (var setting in componentSettings)
                {
                    foreach (var member in setting.GetMembers())
                    {
                        var attr = member.GetAttribute <MetaDataAttribute>();
                        if (attr != null && attr.PromptUser)
                        {
                            AnyMetaData = true;
                            componentSettingsWithMetaData.Add(setting);
                        }
                    }
                }

                foreach (var resource in resources)
                {
                    var type = TypeData.GetTypeData(resource);
                    foreach (var __prop in type.GetMembers())
                    {
                        IMemberData prop = __prop;
                        var         attr = prop.GetAttribute <MetaDataAttribute>();
                        if (attr != null && attr.PromptUser)
                        {
                            AnyMetaData = true;
                        }
                    }
                }
            }
            catch
            {
                // this is just a defensive catch to make sure that the waithandle is not left unset (and we risk waiting for it indefinitely)
                planRun.PromptWaitHandle.Set();
                throw;
            }

            if (AnyMetaData && EngineSettings.Current.PromptForMetaData)
            {
                TapThread.Start(() =>
                {
                    try
                    {
                        List <object> objects = new List <object>();
                        objects.AddRange(componentSettingsWithMetaData.Select(ComponentSettings.GetCurrent));
                        objects.AddRange(resources);

                        planRun.PromptedResources = resources;
                        var obj = new MetadataPromptObject {
                            Resources = objects
                        };
                        UserInput.Request(obj, false);
                        if (obj.Response == MetadataPromptObject.PromptResponse.Abort)
                        {
                            planRun.MainThread.Abort();
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Debug(e);
                        planRun.MainThread.Abort("Error occured while executing platform requests. Metadata prompt can be disabled from the Engine settings menu.");
                    }
                    finally
                    {
                        planRun.PromptWaitHandle.Set();
                    }
                }, name: "Request Metadata");
            }
            else
            {
                planRun.PromptWaitHandle.Set();
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Tries to deserialize an object from an XElement.
        /// </summary>
        /// <param name="element"></param>
        /// <param name="t"></param>
        /// <param name="setter"></param>
        /// <param name="newobj"></param>
        /// <param name="logWarnings">Whether warning messages should be emitted in case of missing properties.</param>
        /// <returns>True on success.</returns>
        public virtual bool TryDeserializeObject(XElement element, ITypeData t, Action <object> setter, object newobj = null, bool logWarnings = true)
        {
            if (element.IsEmpty && !element.HasAttributes)
            {
                setter(null);
                return(true);
            }
            if (newobj == null)
            {
                try
                {
                    newobj = t.CreateInstance(Array.Empty <object>());
                    t      = TypeData.GetTypeData(newobj);
                }
                catch (TargetInvocationException ex)
                {
                    if (ex.InnerException is System.ComponentModel.LicenseException)
                    {
                        throw new Exception(string.Format("Could not create an instance of '{0}': {1}", t.GetAttribute <DisplayAttribute>().Name, ex.InnerException.Message));
                    }
                    else
                    {
                        ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                    }
                }
            }

            var prevobj = Object;

            Object = newobj;
            var t2 = t;

            if (newobj == null)
            {
                throw new ArgumentNullException(nameof(newobj));
            }
            var properties = t2.GetMembers()
                             .Where(x => x.HasAttribute <XmlIgnoreAttribute>() == false)
                             .ToArray();

            try
            {
                foreach (var prop in properties)
                {
                    var attr = prop.GetAttribute <XmlAttributeAttribute>();
                    if (attr == null)
                    {
                        continue;
                    }
                    var name       = string.IsNullOrWhiteSpace(attr.AttributeName) ? prop.Name : attr.AttributeName;
                    var attr_value = element.Attribute(XmlConvert.EncodeLocalName(name));
                    var p          = prop as MemberData;

                    if (p != null && attr_value != null && p.Member is PropertyInfo csprop)
                    {
                        try
                        {
                            readContentInternal(csprop.PropertyType, false, () => attr_value.Value, element, out object value);

                            p.SetValue(newobj, value);
                        }
                        catch (Exception e)
                        {
                            if (logWarnings)
                            {
                                Log.Warning(element, "Attribute value '{0}' was not read correctly as a {1}", attr_value.Value, p);
                                Log.Debug(e);
                            }
                        }
                    }
                }

                if (properties.FirstOrDefault(x => x.HasAttribute <XmlTextAttribute>()) is IMemberData mem2)
                {
                    object value;
                    if (mem2.TypeDescriptor is TypeData td &&
                        readContentInternal(td.Load(), false, () => element.Value, element, out object _value))
                    {
                        value = _value;
                    }
                    else
                    {
                        value = StringConvertProvider.FromString(element.Value, mem2.TypeDescriptor, null);
                    }
                    mem2.SetValue(newobj, value);
                }
                else
                {
                    var    props    = properties.ToLookup(x => x.GetAttributes <XmlElementAttribute>().FirstOrDefault()?.ElementName ?? x.Name);
                    var    elements = element.Elements().ToArray();
                    bool[] visited  = new bool[elements.Length];

                    double order = 0;
                    int    foundWithCurrentType = 0;
                    while (true)
                    {
                        double nextOrder = 1000;
                        // since the object might be dynamically adding properties as other props are added.
                        // we need to iterate a bit. Example: Test Plan Reference.

                        int found = visited.Count(x => x);
                        for (int i = 0; i < elements.Length; i++)
                        {
                            var element2 = elements[i];
                            if (visited[i])
                            {
                                continue;
                            }
                            if (element2.Attribute(IgnoreMemberXName) is XAttribute attr && attr.Value == "true")
                            {
                                visited[i] = true;
                                continue;
                            }
                            IMemberData property        = null;
                            var         name            = XmlConvert.DecodeName(element2.Name.LocalName);
                            var         propertyMatches = props[name];

                            int hits = 0;
                            foreach (var p in propertyMatches)
                            {
                                if (p.Writable || p.HasAttribute <XmlIgnoreAttribute>())
                                {
                                    property = p;
                                    hits++;
                                }
                            }

                            if (0 == hits)
                            {
                                try
                                {
                                    if (property == null)
                                    {
                                        property = t2.GetMember(name);
                                    }
                                    if (property == null)
                                    {
                                        property = t2.GetMembers().FirstOrDefault(x => x.Name == name);
                                    }
                                }
                                catch { }
                                if (property == null || property.Writable == false)
                                {
                                    continue;
                                }
                                hits = 1;
                            }
                            if (hits > 1)
                            {
                                Log.Warning(element2, "Multiple properties named '{0}' are available to the serializer in '{1}' this might give issues in serialization.", element2.Name.LocalName, t.GetAttribute <DisplayAttribute>().Name);
                            }

                            if (property.GetAttribute <DeserializeOrderAttribute>() is DeserializeOrderAttribute orderAttr)
                            {
                                if (order < orderAttr.Order)
                                {
                                    if (orderAttr.Order < nextOrder)
                                    {
                                        nextOrder = orderAttr.Order;
                                    }
                                    continue;
                                }
                            }
                            else
                            {
                                nextOrder = order;
                            }

                            visited[i] = true;
                            var prev = CurrentMember;
                            CurrentMember = property;
                            try
                            {
                                if (CurrentMember.HasAttribute <XmlIgnoreAttribute>())      // This property shouldn't have been in the file in the first place, but in case it is (because of a change or a bug), we shouldn't try to set it. (E.g. SweepLoopRange.SweepStep)
                                {
                                    if (!CurrentMember.HasAttribute <BrowsableAttribute>()) // In the special case we assume that this is some compatibility property that still needs to be set if present in the XML. (E.g. TestPlanReference.DynamicDataContents)
                                    {
                                        continue;
                                    }
                                }

                                if (property is MemberData mem && mem.Member is PropertyInfo Property && Property.PropertyType.HasInterface <IList>() && Property.PropertyType.IsGenericType && Property.HasAttribute <XmlElementAttribute>())
                                {
                                    // Special case to mimic old .NET XmlSerializer behavior
                                    var             list     = (IList)Property.GetValue(newobj);
                                    Action <object> setValue = x => list.Add(x);
                                    Serializer.Deserialize(element2, setValue, Property.PropertyType.GetGenericArguments().First());
                                }
                                else
                                {
                                    Action <object> setValue = x =>
                                    {
                                        var current = property.GetValue(newobj);
                                        property.SetValue(newobj, x);
                                        if (false == Equals(current, x))
                                        { // for some value-like type, it may be needed
                                            // to set the parent object when a property is changed
                                            // example: complex test plan parameters.
                                            setter(newobj);
                                        }
                                    };
                                    Serializer.Deserialize(element2, setValue, property.TypeDescriptor);
                                }
                            }