Beispiel #1
0
        /// <summary>
        /// Create a new instance of a multi-columned <see cref="TableAlertProperty{T}"/> based on the given values.
        /// </summary>
        /// <param name="tableRows">The values of the table rows.</param>
        /// <param name="tablePropertyName">The table property name.</param>
        /// <param name="tableDisplayName">The table property display name.</param>
        /// <param name="tableRowType">The type of the table's rows.</param>
        /// <param name="tableAttribute">The attribute applied to the table property.</param>
        /// <param name="order">The order to use</param>
        /// <returns>The newly created <see cref="TableAlertProperty{T}"/> instance.</returns>
        private static TableAlertProperty <Dictionary <string, string> > CreateMultiColumnTableAlertProperty(
            IList tableRows,
            string tablePropertyName,
            string tableDisplayName,
            Type tableRowType,
            TablePropertyAttribute tableAttribute,
            Order order)
        {
            // Create the table columns
            var rows = new List <Dictionary <string, string> >(tableRows.Count);

            // Initialize the table rows with new dictionaries
            for (int i = 0; i < tableRows.Count; i++)
            {
                rows.Add(new Dictionary <string, string>());
            }

            // We scan the table by columns to we'll handle a single property at a time
            foreach (PropertyInfo columnProperty in tableRowType.GetProperties())
            {
                // Handle only table column properties
                TableColumnAttribute tableColumnAttribute = columnProperty.GetCustomAttribute <TableColumnAttribute>();
                if (tableColumnAttribute != null)
                {
                    for (int i = 0; i < tableRows.Count; i++)
                    {
                        rows[i][columnProperty.Name] = PropertyValueToString(
                            tableRows[i],
                            columnProperty,
                            columnProperty.GetValue(tableRows[i]),
                            tableColumnAttribute.FormatString);
                    }
                }
            }

            return(new TableAlertProperty <Dictionary <string, string> >(tablePropertyName, tableDisplayName, order.Next(), tableAttribute.ShowHeaders, CreateTableColumns(tableRowType), rows));
        }
Beispiel #2
0
        /// <summary>
        /// Create a table alert property based on the given values.
        /// </summary>
        /// <param name="propertyValue">The property value, this must be an instance of <see cref="IList{T}"/>.</param>
        /// <param name="propertyName">The table property name.</param>
        /// <param name="displayName">The table property display name.</param>
        /// <param name="tableAttribute">The attribute applied to the table property.</param>
        /// <param name="order">The order to use</param>
        /// <returns>The newly created <see cref="TableAlertProperty{T}"/> instance.</returns>
        private static DisplayableAlertProperty CreateTableAlertProperty(
            object propertyValue,
            string propertyName,
            string displayName,
            TablePropertyAttribute tableAttribute,
            Order order)
        {
            if (propertyValue is PropertyReference propertyReferenceValue)
            {
                if (tableAttribute is SingleColumnTablePropertyAttribute)
                {
                    return(new TableReferenceAlertProperty(propertyName, displayName, order.Next(), tableAttribute.ShowHeaders, propertyReferenceValue.ReferencePath, propertyReferenceValue.IsOptional, propertyReferenceValue.IsPropertySerialized));
                }

                // tableAttribute is MultiColumnTablePropertyAttribute
                Type propertyValueType = propertyReferenceValue.GetType();
                if (!propertyValueType.IsGenericType || propertyValueType.GetGenericTypeDefinition() != typeof(TablePropertyReference <>))
                {
                    throw new ArgumentException($"A {nameof(MultiColumnTablePropertyAttribute)} used as property reference can only be applied to properties of type TablePropertyReference<T>");
                }

                Type tableReferenceRowType = propertyValueType.GetGenericArguments().Single();
                if (tableReferenceRowType
                    .GetProperties()
                    .Any(prop => !string.IsNullOrEmpty(prop.GetCustomAttribute <TableColumnAttribute>()?.FormatString)))
                {
                    throw new ArgumentException($"The columns of a {nameof(MultiColumnTablePropertyAttribute)} applied to properties of type {nameof(PropertyReference)} cannot have format strings");
                }

                return(new TableReferenceAlertProperty(
                           propertyName, displayName, order.Next(), tableAttribute.ShowHeaders, CreateTableColumns(tableReferenceRowType), propertyReferenceValue.ReferencePath, propertyReferenceValue.IsOptional, propertyReferenceValue.IsPropertySerialized));
            }

            // Validate we have a proper value
            if (!(propertyValue is IList tablePropertyValue))
            {
                throw new ArgumentException($"A {nameof(TablePropertyAttribute)} can only be applied to properties of type IList");
            }

            // Validate the table is not empty (shouldn't happen, empty tables are ignored by ExtractProperties)
            if (tablePropertyValue.Count == 0)
            {
                throw new ArgumentException("Unexpected empty list encountered");
            }

            // Get element type, and verify that all elements are of the same type
            Type  tableRowType    = tablePropertyValue[0].GetType();
            IList typedTableValue = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(tableRowType));

            foreach (object item in tablePropertyValue)
            {
                if (item.GetType() != tableRowType)
                {
                    throw new ArgumentException($"All items in a list with {nameof(TablePropertyAttribute)} must have the same type");
                }

                typedTableValue.Add(item);
            }

            // Easy way out if we're handling a single-column table
            if (tableAttribute is SingleColumnTablePropertyAttribute)
            {
                Type tablePropertyType = typeof(TableAlertProperty <>).MakeGenericType(tableRowType);
                return((DisplayableAlertProperty)Activator.CreateInstance(
                           tablePropertyType,
                           propertyName,
                           displayName,
                           order.Next(),
                           tableAttribute.ShowHeaders,
                           typedTableValue));
            }

            return(CreateMultiColumnTableAlertProperty(tablePropertyValue, propertyName, displayName, tableRowType, tableAttribute, order));
        }