/mcs/class/System.ComponentModel.Composition.4.5/src/ComponentModel/System/ComponentModel/Composition/ReflectionModel/GenericSpecializationPartCreationInfo.cs
C# | 564 lines | 455 code | 93 blank | 16 comment | 61 complexity | 079fc7893459e11cbf85775cfff5b7d6 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
- // -----------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // -----------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.Composition.Primitives;
- using System.Diagnostics.CodeAnalysis;
- using System.Globalization;
- using System.Linq;
- using System.Reflection;
- using Microsoft.Internal;
- using Microsoft.Internal.Collections;
- using System.Diagnostics.Contracts;
- using System.Threading;
- using System.ComponentModel.Composition.Hosting;
- namespace System.ComponentModel.Composition.ReflectionModel
- {
- internal class GenericSpecializationPartCreationInfo : IReflectionPartCreationInfo
- {
- private readonly IReflectionPartCreationInfo _originalPartCreationInfo;
- private readonly ReflectionComposablePartDefinition _originalPart;
- private readonly Type[] _specialization;
- private readonly string[] _specializationIdentities;
- private IEnumerable<ExportDefinition> _exports;
- private IEnumerable<ImportDefinition> _imports;
- private readonly Lazy<Type> _lazyPartType;
- private List<LazyMemberInfo> _members;
- private List<Lazy<ParameterInfo>> _parameters;
- private Dictionary<LazyMemberInfo, MemberInfo[]> _membersTable;
- private Dictionary<Lazy<ParameterInfo>, ParameterInfo> _parametersTable;
- private ConstructorInfo _constructor;
- private object _lock = new object();
- public GenericSpecializationPartCreationInfo(IReflectionPartCreationInfo originalPartCreationInfo, ReflectionComposablePartDefinition originalPart, Type[] specialization)
- {
- Assumes.NotNull(originalPartCreationInfo);
- Assumes.NotNull(specialization);
- Assumes.NotNull(originalPart);
- this._originalPartCreationInfo = originalPartCreationInfo;
- this._originalPart = originalPart;
- this._specialization = specialization;
- this._specializationIdentities = new string[this._specialization.Length];
- for (int i = 0; i < this._specialization.Length; i++)
- {
- this._specializationIdentities[i] = AttributedModelServices.GetTypeIdentity(this._specialization[i]);
- }
- this._lazyPartType = new Lazy<Type>(
- () => this._originalPartCreationInfo.GetPartType().MakeGenericType(specialization),
- LazyThreadSafetyMode.PublicationOnly);
- }
- public ReflectionComposablePartDefinition OriginalPart
- {
- get
- {
- return this._originalPart;
- }
- }
- public Type GetPartType()
- {
- return this._lazyPartType.Value;
- }
- public Lazy<Type> GetLazyPartType()
- {
- return this._lazyPartType;
- }
- public ConstructorInfo GetConstructor()
- {
- if (this._constructor == null)
- {
- ConstructorInfo genericConstuctor = this._originalPartCreationInfo.GetConstructor();
- ConstructorInfo result = null;
- if (genericConstuctor != null)
- {
- foreach (ConstructorInfo constructor in this.GetPartType().GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
- {
- if (constructor.MetadataToken == genericConstuctor.MetadataToken)
- {
- result = constructor;
- break;
- }
- }
- }
- Thread.MemoryBarrier();
- lock (this._lock)
- {
- if (this._constructor == null)
- {
- this._constructor = result;
- }
- }
- }
- return this._constructor;
- }
- public IDictionary<string, object> GetMetadata()
- {
- var originalMetadata = new Dictionary<string, object>(this._originalPartCreationInfo.GetMetadata(), StringComparers.MetadataKeyNames);
- originalMetadata.Remove(CompositionConstants.IsGenericPartMetadataName);
- originalMetadata.Remove(CompositionConstants.GenericPartArityMetadataName);
- originalMetadata.Remove(CompositionConstants.GenericParameterConstraintsMetadataName);
- originalMetadata.Remove(CompositionConstants.GenericParameterAttributesMetadataName);
- return originalMetadata;
- }
- private MemberInfo[] GetAccessors(LazyMemberInfo originalLazyMember)
- {
- this.BuildTables();
- Assumes.NotNull(this._membersTable);
- return this._membersTable[originalLazyMember];
- }
- private ParameterInfo GetParameter(Lazy<ParameterInfo> originalParameter)
- {
- this.BuildTables();
- Assumes.NotNull(this._parametersTable);
- return this._parametersTable[originalParameter];
- }
- private void BuildTables()
- {
- if (this._membersTable != null)
- {
- return;
- }
- this.PopulateImportsAndExports();
- List<LazyMemberInfo> members = null;
- List<Lazy<ParameterInfo>> parameters = null;
- lock (this._lock)
- {
- if (this._membersTable == null)
- {
- members = this._members;
- parameters = this._parameters;
- Assumes.NotNull(members);
- }
- }
- //
- // Get all members that can be of interest and extract their MetadataTokens
- //
- Dictionary<LazyMemberInfo, MemberInfo[]> membersTable = this.BuildMembersTable(members);
- Dictionary<Lazy<ParameterInfo>, ParameterInfo> parametersTable = this.BuildParametersTable(parameters);
- lock (this._lock)
- {
- if (this._membersTable == null)
- {
- this._membersTable = membersTable;
- this._parametersTable = parametersTable;
- Thread.MemoryBarrier();
- this._parameters = null;
- this._members = null;
- }
- }
- }
- private Dictionary<LazyMemberInfo, MemberInfo[]> BuildMembersTable(List<LazyMemberInfo> members)
- {
- Assumes.NotNull(members);
- Dictionary<LazyMemberInfo, MemberInfo[]> membersTable = new Dictionary<LazyMemberInfo, MemberInfo[]>();
- Dictionary<int, MemberInfo> specializedPartMembers = new Dictionary<int, MemberInfo>();
- Type closedGenericPartType = this.GetPartType();
- specializedPartMembers[closedGenericPartType.MetadataToken] = closedGenericPartType;
- foreach (MethodInfo method in closedGenericPartType.GetAllMethods())
- {
- specializedPartMembers[method.MetadataToken] = method;
- }
- foreach (FieldInfo field in closedGenericPartType.GetAllFields())
- {
- specializedPartMembers[field.MetadataToken] = field;
- }
- //
- // Now go through the members table and resolve them into the new closed type based on the tokens
- //
- foreach (LazyMemberInfo lazyMemberInfo in members)
- {
- MemberInfo[] genericAccessors = lazyMemberInfo.GetAccessors();
- MemberInfo[] accessors = new MemberInfo[genericAccessors.Length];
- for (int i = 0; i < genericAccessors.Length; i++)
- {
- // GENTODO - error case? Very unlikely, but still?
- accessors[i] = (genericAccessors[i] != null) ? specializedPartMembers[genericAccessors[i].MetadataToken] : null;
- }
- membersTable[lazyMemberInfo] = accessors;
- }
- return membersTable;
- }
- private Dictionary<Lazy<ParameterInfo>, ParameterInfo> BuildParametersTable(List<Lazy<ParameterInfo>> parameters)
- {
- if (parameters != null)
- {
- Dictionary<Lazy<ParameterInfo>, ParameterInfo> parametersTable = new Dictionary<Lazy<ParameterInfo>, ParameterInfo>();
- // GENTODO - error case
- ParameterInfo[] constructorParameters = this.GetConstructor().GetParameters();
- foreach (var lazyParameter in parameters)
- {
- parametersTable[lazyParameter] = constructorParameters[lazyParameter.Value.Position];
- }
- return parametersTable;
- }
- else
- {
- return null;
- }
- }
- private List<ImportDefinition> PopulateImports(List<LazyMemberInfo> members, List<Lazy<ParameterInfo>> parameters)
- {
- List<ImportDefinition> imports = new List<ImportDefinition>();
- foreach (ImportDefinition originalImport in this._originalPartCreationInfo.GetImports())
- {
- ReflectionImportDefinition reflectionImport = originalImport as ReflectionImportDefinition;
- if (reflectionImport == null)
- {
- // we always ignore these
- continue;
- }
- imports.Add(this.TranslateImport(reflectionImport, members, parameters));
- }
- return imports;
- }
- private ImportDefinition TranslateImport(ReflectionImportDefinition reflectionImport, List<LazyMemberInfo> members, List<Lazy<ParameterInfo>> parameters)
- {
- bool isExportFactory = false;
- ContractBasedImportDefinition productImport = reflectionImport;
- IPartCreatorImportDefinition exportFactoryImportDefinition = reflectionImport as IPartCreatorImportDefinition;
- if (exportFactoryImportDefinition != null)
- {
- productImport = exportFactoryImportDefinition.ProductImportDefinition;
- isExportFactory = true;
- }
- string contractName = this.Translate(productImport.ContractName);
- string requiredTypeIdentity = this.Translate(productImport.RequiredTypeIdentity);
- IDictionary<string, object> metadata = this.TranslateImportMetadata(productImport);
-
- ReflectionMemberImportDefinition memberImport = reflectionImport as ReflectionMemberImportDefinition;
- ImportDefinition import = null;
- if (memberImport != null)
- {
- LazyMemberInfo lazyMember = memberImport.ImportingLazyMember;
- LazyMemberInfo importingMember = new LazyMemberInfo(lazyMember.MemberType, () => GetAccessors(lazyMember));
- if (isExportFactory)
- {
- import = new PartCreatorMemberImportDefinition(
- importingMember,
- ((ICompositionElement)memberImport).Origin,
- new ContractBasedImportDefinition(
- contractName,
- requiredTypeIdentity,
- productImport.RequiredMetadata,
- productImport.Cardinality,
- productImport.IsRecomposable,
- false,
- CreationPolicy.NonShared,
- metadata));
- }
- else
- {
- import = new ReflectionMemberImportDefinition(
- importingMember,
- contractName,
- requiredTypeIdentity,
- productImport.RequiredMetadata,
- productImport.Cardinality,
- productImport.IsRecomposable,
- false,
- productImport.RequiredCreationPolicy,
- metadata,
- ((ICompositionElement)memberImport).Origin);
- }
- members.Add(lazyMember);
- }
- else
- {
- ReflectionParameterImportDefinition parameterImport = reflectionImport as ReflectionParameterImportDefinition;
- Assumes.NotNull(parameterImport);
- Lazy<ParameterInfo> lazyParameter = parameterImport.ImportingLazyParameter;
- Lazy<ParameterInfo> parameter = new Lazy<ParameterInfo>(() => GetParameter(lazyParameter));
- if (isExportFactory)
- {
- import = new PartCreatorParameterImportDefinition(
- parameter,
- ((ICompositionElement)parameterImport).Origin,
- new ContractBasedImportDefinition(
- contractName,
- requiredTypeIdentity,
- productImport.RequiredMetadata,
- productImport.Cardinality,
- false,
- true,
- CreationPolicy.NonShared,
- metadata));
- }
- else
- {
- import = new ReflectionParameterImportDefinition(
- parameter,
- contractName,
- requiredTypeIdentity,
- productImport.RequiredMetadata,
- productImport.Cardinality,
- productImport.RequiredCreationPolicy,
- metadata,
- ((ICompositionElement)parameterImport).Origin);
- }
- parameters.Add(lazyParameter);
- }
- return import;
- }
- private List<ExportDefinition> PopulateExports(List<LazyMemberInfo> members)
- {
- List<ExportDefinition> exports = new List<ExportDefinition>();
- foreach (ExportDefinition originalExport in this._originalPartCreationInfo.GetExports())
- {
- ReflectionMemberExportDefinition reflectionExport = originalExport as ReflectionMemberExportDefinition;
- if (reflectionExport == null)
- {
- // we always ignore these
- continue;
- }
- exports.Add(this.TranslateExpot(reflectionExport, members));
- }
- return exports;
- }
- public ExportDefinition TranslateExpot(ReflectionMemberExportDefinition reflectionExport, List<LazyMemberInfo> members)
- {
- ExportDefinition export = null;
- LazyMemberInfo lazyMember = reflectionExport.ExportingLazyMember;
- var capturedLazyMember = lazyMember;
- var capturedReflectionExport = reflectionExport;
- string contractName = this.Translate(reflectionExport.ContractName, reflectionExport.Metadata.GetValue<int[]>(CompositionConstants.GenericExportParametersOrderMetadataName));
- LazyMemberInfo exportingMember = new LazyMemberInfo(capturedLazyMember.MemberType, () => GetAccessors(capturedLazyMember));
- Lazy<IDictionary<string, object>> lazyMetadata = new Lazy<IDictionary<string, object>>(() => this.TranslateExportMetadata(capturedReflectionExport));
- export = new ReflectionMemberExportDefinition(
- exportingMember,
- new LazyExportDefinition(contractName, lazyMetadata),
- ((ICompositionElement)reflectionExport).Origin);
- members.Add(capturedLazyMember);
- return export;
- }
- private string Translate(string originalValue, int[] genericParametersOrder)
- {
- if (genericParametersOrder != null)
- {
- string[] specializationIdentities = GenericServices.Reorder(this._specializationIdentities, genericParametersOrder);
- return string.Format(CultureInfo.InvariantCulture, originalValue, specializationIdentities);
- }
- else
- {
- return Translate(originalValue);
- }
- }
- private string Translate(string originalValue)
- {
- return string.Format(CultureInfo.InvariantCulture, originalValue, this._specializationIdentities);
- }
- private IDictionary<string, object> TranslateImportMetadata(ContractBasedImportDefinition originalImport)
- {
- int[] importParametersOrder = originalImport.Metadata.GetValue<int[]>(CompositionConstants.GenericImportParametersOrderMetadataName);
- if (importParametersOrder != null)
- {
- Dictionary<string, object> metadata = new Dictionary<string, object>(originalImport.Metadata, StringComparers.MetadataKeyNames);
- // Get the newly re-qualified name of the generic contract and the subset of applicable types from the specialization
- metadata[CompositionConstants.GenericContractMetadataName] = GenericServices.GetGenericName(originalImport.ContractName, importParametersOrder, this._specialization.Length);
- metadata[CompositionConstants.GenericParametersMetadataName] = GenericServices.Reorder(this._specialization, importParametersOrder);
- metadata.Remove(CompositionConstants.GenericImportParametersOrderMetadataName);
- return metadata.AsReadOnly();
- }
- else
- {
- return originalImport.Metadata;
- }
- }
- private IDictionary<string, object> TranslateExportMetadata(ReflectionMemberExportDefinition originalExport)
- {
- Dictionary<string, object> metadata = new Dictionary<string, object>(originalExport.Metadata, StringComparers.MetadataKeyNames);
- string exportTypeIdentity = originalExport.Metadata.GetValue<string>(CompositionConstants.ExportTypeIdentityMetadataName);
- if (!string.IsNullOrEmpty(exportTypeIdentity))
- {
- metadata[CompositionConstants.ExportTypeIdentityMetadataName] = this.Translate(exportTypeIdentity, originalExport.Metadata.GetValue<int[]>(CompositionConstants.GenericExportParametersOrderMetadataName));
- }
- metadata.Remove(CompositionConstants.GenericExportParametersOrderMetadataName);
- return metadata;
- }
- private void PopulateImportsAndExports()
- {
- if ((this._exports == null) || (this._imports == null))
- {
- List<LazyMemberInfo> members = new List<LazyMemberInfo>();
- List<Lazy<ParameterInfo>> parameters = new List<Lazy<ParameterInfo>>();
- // we are very careful to not call any 3rd party code in either of these
- var exports = this.PopulateExports(members);
- var imports = this.PopulateImports(members, parameters);
- Thread.MemoryBarrier();
- lock (this._lock)
- {
- if ((this._exports == null) || (this._imports == null))
- {
- this._members = members;
- if (parameters.Count > 0)
- {
- this._parameters = parameters;
- }
- this._exports = exports;
- this._imports = imports;
- }
- }
- }
- }
- public IEnumerable<ExportDefinition> GetExports()
- {
- this.PopulateImportsAndExports();
- return this._exports;
- }
- public IEnumerable<ImportDefinition> GetImports()
- {
- this.PopulateImportsAndExports();
- return this._imports;
- }
- public bool IsDisposalRequired
- {
- get { return this._originalPartCreationInfo.IsDisposalRequired; }
- }
- public string DisplayName
- {
- get { return this.Translate(this._originalPartCreationInfo.DisplayName); }
- }
- public ICompositionElement Origin
- {
- get { return this._originalPartCreationInfo.Origin; }
- }
- public override bool Equals(object obj)
- {
- GenericSpecializationPartCreationInfo that = obj as GenericSpecializationPartCreationInfo;
- if (that == null)
- {
- return false;
- }
- return (this._originalPartCreationInfo.Equals(that._originalPartCreationInfo)) &&
- (this._specialization.IsArrayEqual(that._specialization));
- }
- public override int GetHashCode()
- {
- return this._originalPartCreationInfo.GetHashCode();
- }
- public static bool CanSpecialize(IDictionary<string, object> partMetadata, Type[] specialization)
- {
- int partArity = partMetadata.GetValue<int>(CompositionConstants.GenericPartArityMetadataName);
- if (partArity != specialization.Length)
- {
- return false;
- }
- object[] genericParameterConstraints = partMetadata.GetValue<object[]>(CompositionConstants.GenericParameterConstraintsMetadataName);
- GenericParameterAttributes[] genericParameterAttributes = partMetadata.GetValue<GenericParameterAttributes[]>(CompositionConstants.GenericParameterAttributesMetadataName);
- // if no constraints and attributes been specifed, anything can be created
- if ((genericParameterConstraints == null) && (genericParameterAttributes == null))
- {
- return true;
- }
- if ((genericParameterConstraints != null) && (genericParameterConstraints.Length != partArity))
- {
- return false;
- }
- if ((genericParameterAttributes != null) && (genericParameterAttributes.Length != partArity))
- {
- return false;
- }
- for (int i = 0; i < partArity; i++)
- {
- if (!GenericServices.CanSpecialize(
- specialization[i],
- (genericParameterConstraints[i] as Type[]).CreateTypeSpecializations(specialization),
- genericParameterAttributes[i]))
- {
- return false;
- }
- }
- return true;
- }
- }
- }