Use ENUM MetaField as property on your product/variation

Sometimes you may want to use an enum from Business Foundation on your product/variation. In my case the “Organization Customer Group” that can be set on an Organization.

For this you need a custom “SelectManyAttribute” and a “SelectionFactory”.

public sealed class MetaEnumSelectionAttribute : SelectManyAttribute, IMetadataAware
    {
        public string McDataTypeName { get; }

        public MetaEnumSelectionAttribute(string mcDataTypeName)
        {
            this.McDataTypeName = mcDataTypeName;
        }

        public new void OnMetadataCreated(ModelMetadata metadata)
        {
            if (metadata == null)
            {
                return;
            }

            this.SelectionFactoryType = typeof(MetaEnumSelectionFactory);

            base.OnMetadataCreated(metadata);
        }
    }

This attribute doe not do more than set the selection factory and the name of the enum you need.

public class MetaEnumSelectionFactory : ISelectionFactory
    {
        private static readonly ILogger Log = LogManager.GetLogger();

        public IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
        {
            try
            {
                MetaEnumSelectionAttribute metaEnumSelectionAttribute =
                    metadata.Attributes.OfType<MetaEnumSelectionAttribute>().SingleOrDefault();

                MetaFieldType currentType = null;

                if (metaEnumSelectionAttribute != null
                    && !string.IsNullOrEmpty(metaEnumSelectionAttribute.McDataTypeName))
                {
                    currentType =
                        DataContext.Current.MetaModel.RegisteredTypes.Cast<MetaFieldType>()
                            .FirstOrDefault(
                                type =>
                                type.McDataType == McDataType.Enum
                                && type.Name.Equals(
                                    metaEnumSelectionAttribute.McDataTypeName, 
                                    StringComparison.OrdinalIgnoreCase));
                }

                if (currentType == null)
                {
                    return new List<ISelectItem>();
                }

                MetaEnumItem[] values = MetaEnum.GetItems(currentType);

                return
                    values.Select(
                        metaEnumItem =>
                        new SelectItem
                            {
                                Text = MetaEnum.GetFriendlyName(currentType, metaEnumItem.Handle), 
                                Value = metaEnumItem.Handle.ToString()
                            }).Cast<ISelectItem>().ToList();
            }
            catch (ArgumentNullException argumentNullException)
            {
                Log.Error(argumentNullException.Message, argumentNullException);
            }
            catch (ArgumentException argumentException)
            {
                Log.Error(argumentException.Message, argumentException);
            }
            catch (InvalidOperationException invalidOperationException)
            {
                Log.Error(invalidOperationException.Message, invalidOperationException);
            }
            catch (InvalidCastException invalidCastException)
            {
                Log.Error(invalidCastException.Message, invalidCastException);
            }

            return new List<ISelectItem>();
        }

The selection factory gets the enum from the registered types in the context by the name specified in the attribute and returns a list of select items based on the items in the enum.

On your product/variation you can add property with the attribute, select the values and use them.

[MetaEnumSelection("ContactGroup")]
public virtual string Customergroups { get; set; }

The complete code can be found here

Leave a comment