File: System\ComponentModel\Composition\ReflectionModel\ImportingItem.cs
Web Access
Project: src\src\libraries\System.ComponentModel.Composition\src\System.ComponentModel.Composition.csproj (System.ComponentModel.Composition)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.ComponentModel.Composition.Primitives;
using System.Globalization;
using Microsoft.Internal;
 
namespace System.ComponentModel.Composition.ReflectionModel
{
    internal abstract class ImportingItem
    {
        private readonly ContractBasedImportDefinition _definition;
        private readonly ImportType _importType;
 
        protected ImportingItem(ContractBasedImportDefinition definition, ImportType importType)
        {
            ArgumentNullException.ThrowIfNull(definition);
 
            _definition = definition;
            _importType = importType;
        }
 
        public ContractBasedImportDefinition Definition
        {
            get { return _definition; }
        }
 
        public ImportType ImportType
        {
            get { return _importType; }
        }
 
        public object? CastExportsToImportType(Export[] exports)
        {
            if (Definition.Cardinality == ImportCardinality.ZeroOrMore)
            {
                return CastExportsToCollectionImportType(exports);
            }
            else
            {
                return CastExportsToSingleImportType(exports);
            }
        }
 
        private Array CastExportsToCollectionImportType(Export[] exports)
        {
            ArgumentNullException.ThrowIfNull(exports);
 
            // Element type could be null if the actually import type of the member is not a collection
            // This particular case will end up failing when we set the member.
            Type elementType = ImportType.ElementType ?? typeof(object);
 
            Array array = Array.CreateInstance(elementType, exports.Length);
 
            for (int i = 0; i < array.Length; i++)
            {
                object? value = CastSingleExportToImportType(elementType, exports[i]);
 
                array.SetValue(value, i);
            }
 
            return array;
        }
 
        private object? CastExportsToSingleImportType(Export[] exports)
        {
            ArgumentNullException.ThrowIfNull(exports);
 
            if (exports.Length >= 2)
            {
                throw new Exception(SR.Diagnostic_InternalExceptionMessage);
            }
 
            if (exports.Length == 0)
            {
                return null;
            }
 
            return CastSingleExportToImportType(ImportType.ActualType, exports[0]);
        }
 
        private object? CastSingleExportToImportType(Type type, Export export)
        {
            if (ImportType.CastExport != null)
            {
                return ImportType.CastExport(export);
            }
 
            return Cast(type, export);
        }
 
        private object? Cast(Type type, Export export)
        {
            object? value = export.Value;
 
            if (!ContractServices.TryCast(type, value, out object? result))
            {
                throw new ComposablePartException(
                    SR.Format(
                        SR.ReflectionModel_ImportNotAssignableFromExport,
                        export.ToElement().DisplayName,
                        type.FullName),
                    Definition.ToElement());
            }
 
            return result;
        }
    }
}