File: System\Composition\Convention\ExportConventionBuilder.cs
Web Access
Project: src\src\libraries\System.Composition.Convention\src\System.Composition.Convention.csproj (System.Composition.Convention)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Composition;
using System.Linq;
using System.Reflection;
using System.Text;
 
namespace System.Composition.Convention
{
    /// <summary>
    /// Configures an export associated with a part.
    /// </summary>
    public sealed class ExportConventionBuilder
    {
        private string _contractName;
        private Type _contractType;
        private List<Tuple<string, object>> _metadataItems;
        private List<Tuple<string, Func<Type, object>>> _metadataItemFuncs;
        private Func<Type, string> _getContractNameFromPartType;
 
        internal ExportConventionBuilder() { }
 
        /// <summary>
        /// Specify the contract type for the export.
        /// </summary>
        /// <typeparam name="T">The contract type.</typeparam>
        /// <returns>An export builder allowing further configuration.</returns>
        public ExportConventionBuilder AsContractType<T>()
        {
            return AsContractType(typeof(T));
        }
 
        /// <summary>
        /// Specify the contract type for the export.
        /// </summary>
        /// <param name="type">The contract type.</param>
        /// <returns>An export builder allowing further configuration.</returns>
        public ExportConventionBuilder AsContractType(Type type)
        {
            if (type is null)
            {
                throw new ArgumentNullException(nameof(type));
            }
 
            _contractType = type;
            return this;
        }
 
        /// <summary>
        /// Specify the contract name for the export.
        /// </summary>
        /// <param name="contractName">The contract name.</param>
        /// <returns>An export builder allowing further configuration.</returns>
        public ExportConventionBuilder AsContractName(string contractName)
        {
            if (contractName is null)
            {
                throw new ArgumentNullException(nameof(contractName));
            }
 
            if (contractName.Length == 0)
            {
                throw new ArgumentException(SR.Format(SR.ArgumentException_EmptyString, nameof(contractName)), nameof(contractName));
            }
            _contractName = contractName;
            return this;
        }
 
        /// <summary>
        /// Specify the contract name for the export.
        /// </summary>
        /// <param name="getContractNameFromPartType">A Func to retrieve the contract name from the part typeThe contract name.</param>
        /// <returns>An export builder allowing further configuration.</returns>
        public ExportConventionBuilder AsContractName(Func<Type, string> getContractNameFromPartType)
        {
            if (getContractNameFromPartType is null)
            {
                throw new ArgumentNullException(nameof(getContractNameFromPartType));
            }
 
            _getContractNameFromPartType = getContractNameFromPartType;
            return this;
        }
 
        /// <summary>
        /// Add export metadata to the export.
        /// </summary>
        /// <param name="name">The name of the metadata item.</param>
        /// <param name="value">The value of the metadata item.</param>
        /// <returns>An export builder allowing further configuration.</returns>
        public ExportConventionBuilder AddMetadata(string name, object value)
        {
            if (name is null)
            {
                throw new ArgumentNullException(nameof(name));
            }
 
            if (name.Length == 0)
            {
                throw new ArgumentException(SR.Format(SR.ArgumentException_EmptyString, nameof(name)), nameof(name));
            }
 
            _metadataItems ??= new List<Tuple<string, object>>();
            _metadataItems.Add(Tuple.Create(name, value));
            return this;
        }
 
        /// <summary>
        /// Add export metadata to the export.
        /// </summary>
        /// <param name="name">The name of the metadata item.</param>
        /// <param name="getValueFromPartType">A function that calculates the metadata value based on the type.</param>
        /// <returns>An export builder allowing further configuration.</returns>
        public ExportConventionBuilder AddMetadata(string name, Func<Type, object> getValueFromPartType)
        {
            if (name is null)
            {
                throw new ArgumentNullException(nameof(name));
            }
            if (getValueFromPartType is null)
            {
                throw new ArgumentNullException(nameof(getValueFromPartType));
            }
 
            if (name.Length == 0)
            {
                throw new ArgumentException(SR.Format(SR.ArgumentException_EmptyString, nameof(name)), nameof(name));
            }
 
            _metadataItemFuncs ??= new List<Tuple<string, Func<Type, object>>>();
            _metadataItemFuncs.Add(Tuple.Create(name, getValueFromPartType));
            return this;
        }
 
        internal void BuildAttributes(Type type, ref List<Attribute> attributes)
        {
            attributes ??= new List<Attribute>();
 
            var contractName = (_getContractNameFromPartType != null) ? _getContractNameFromPartType(type) : _contractName;
            attributes.Add(new ExportAttribute(contractName, _contractType));
 
            //Add metadata attributes from direct specification
            if (_metadataItems != null)
            {
                foreach (Tuple<string, object> item in _metadataItems)
                {
                    attributes.Add(new ExportMetadataAttribute(item.Item1, item.Item2));
                }
            }
 
            //Add metadata attributes from func specification
            if (_metadataItemFuncs != null)
            {
                foreach (Tuple<string, Func<Type, object>> item in _metadataItemFuncs)
                {
                    var name = item.Item1;
                    var value = (item.Item2 != null) ? item.Item2(type) : null;
                    attributes.Add(new ExportMetadataAttribute(name, value));
                }
            }
        }
    }
}