/mcs/class/System.ComponentModel.Composition/src/ComponentModel/System/ComponentModel/Composition/ConstraintServices.cs
https://github.com/iainlane/mono · C# · 214 lines · 154 code · 38 blank · 22 comment · 13 complexity · d4af4eb6dcfe42351e8aaa1fc7347d93 MD5 · raw file
- // -----------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // -----------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.Composition.Hosting;
- using System.ComponentModel.Composition.Primitives;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using Microsoft.Internal;
-
- namespace System.ComponentModel.Composition
- {
- internal static class ConstraintServices
- {
- // NOTE : these are here as Reflection member search is pretty expensive, and we want that to be done once.
- // Also, making these static would cause this class to fail loading if we rename members of ExportDefinition.
- private static readonly PropertyInfo _exportDefinitionContractNameProperty = typeof(ExportDefinition).GetProperty("ContractName");
- private static readonly PropertyInfo _exportDefinitionMetadataProperty = typeof(ExportDefinition).GetProperty("Metadata");
- private static readonly MethodInfo _metadataContainsKeyMethod = typeof(IDictionary<string, object>).GetMethod("ContainsKey");
- private static readonly MethodInfo _metadataItemMethod = typeof(IDictionary<string, object>).GetMethod("get_Item");
- private static readonly MethodInfo _metadataEqualsMethod = typeof(object).GetMethod("Equals", new Type[] { typeof(object) });
- private static readonly MethodInfo _typeIsInstanceOfTypeMethod = typeof(Type).GetMethod("IsInstanceOfType");
-
- public static Expression<Func<ExportDefinition, bool>> CreateConstraint(IEnumerable<KeyValuePair<string, Type>> requiredMetadata)
- {
- ParameterExpression parameter = Expression.Parameter(typeof(ExportDefinition), "exportDefinition");
- Expression metadataConstraintBody = null;
-
- if (requiredMetadata != null)
- {
- metadataConstraintBody = ConstraintServices.CreateMetadataConstraintBody(requiredMetadata, parameter);
- }
-
- if (metadataConstraintBody != null)
- {
- return Expression.Lambda<Func<ExportDefinition, bool>>(metadataConstraintBody, parameter);
- }
-
- return null;
- }
-
- public static Expression<Func<ExportDefinition, bool>> CreateConstraint(string contractName, string requiredTypeIdentity, IEnumerable<KeyValuePair<string, Type>> requiredMetadata, CreationPolicy requiredCreationPolicy)
- {
- ParameterExpression parameter = Expression.Parameter(typeof(ExportDefinition), "exportDefinition");
-
- Expression constraintBody = ConstraintServices.CreateContractConstraintBody(contractName, parameter);
-
- if (!string.IsNullOrEmpty(requiredTypeIdentity))
- {
- Expression typeIdentityConstraintBody = ConstraintServices.CreateTypeIdentityContraint(requiredTypeIdentity, parameter);
-
- constraintBody = Expression.AndAlso(constraintBody, typeIdentityConstraintBody);
- }
-
- if (requiredMetadata != null)
- {
- Expression metadataConstraintBody = ConstraintServices.CreateMetadataConstraintBody(requiredMetadata, parameter);
- if (metadataConstraintBody != null)
- {
- constraintBody = Expression.AndAlso(constraintBody, metadataConstraintBody);
- }
- }
-
- if (requiredCreationPolicy != CreationPolicy.Any)
- {
- Expression policyConstraintBody = ConstraintServices.CreateCreationPolicyContraint(requiredCreationPolicy, parameter);
-
- constraintBody = Expression.AndAlso(constraintBody, policyConstraintBody);
- }
-
- Expression<Func<ExportDefinition, bool>> constraint = Expression.Lambda<Func<ExportDefinition, bool>>(constraintBody, parameter);
- return constraint;
- }
-
- private static Expression CreateContractConstraintBody(string contractName, ParameterExpression parameter)
- {
- Assumes.NotNull(parameter);
-
- // export.ContractName=<contract>;
- return Expression.Equal(
- Expression.Property(parameter, ConstraintServices._exportDefinitionContractNameProperty),
- Expression.Constant(contractName ?? string.Empty, typeof(string)));
- }
-
- private static Expression CreateMetadataConstraintBody(IEnumerable<KeyValuePair<string, Type>> requiredMetadata, ParameterExpression parameter)
- {
- Assumes.NotNull(requiredMetadata);
- Assumes.NotNull(parameter);
-
- Expression body = null;
- foreach (KeyValuePair<string, Type> requiredMetadataItem in requiredMetadata)
- {
- // export.Metadata.ContainsKey(<metadataItem>)
- Expression metadataItemExpression = CreateMetadataContainsKeyExpression(parameter, requiredMetadataItem.Key);
-
- body = (body != null) ? Expression.AndAlso(body, metadataItemExpression) : metadataItemExpression;
- body = Expression.AndAlso(body, CreateMetadataOfTypeExpression(parameter, requiredMetadataItem.Key, requiredMetadataItem.Value));
- }
-
- return body;
- }
-
- private static Expression CreateCreationPolicyContraint(CreationPolicy policy, ParameterExpression parameter)
- {
- Assumes.IsTrue(policy != CreationPolicy.Any);
- Assumes.NotNull(parameter);
-
- // !definition.Metadata.ContainsKey(CompositionConstants.PartCreationPolicyMetadataName) ||
- // CreationPolicy.Any.Equals(definition.Metadata[CompositionConstants.PartCreationPolicyMetadataName]) ||
- // policy.Equals(definition.Metadata[CompositionConstants.PartCreationPolicyMetadataName]);
-
- return Expression.MakeBinary(ExpressionType.OrElse,
- Expression.MakeBinary(ExpressionType.OrElse,
- Expression.Not(CreateMetadataContainsKeyExpression(parameter, CompositionConstants.PartCreationPolicyMetadataName)),
- CreateMetadataValueEqualsExpression(parameter, CreationPolicy.Any, CompositionConstants.PartCreationPolicyMetadataName)),
- CreateMetadataValueEqualsExpression(parameter, policy, CompositionConstants.PartCreationPolicyMetadataName));
- }
-
- private static Expression CreateTypeIdentityContraint(string requiredTypeIdentity, ParameterExpression parameter)
- {
- Assumes.NotNull(requiredTypeIdentity);
- Assumes.NotNull(parameter);
-
- // definition.Metadata.ContainsKey(CompositionServices.ExportTypeIdentity) &&
- // requiredTypeIdentity.Equals(definition.Metadata[CompositionConstants.ExportTypeIdentityMetadataName]);
-
- return Expression.MakeBinary(ExpressionType.AndAlso,
- CreateMetadataContainsKeyExpression(parameter, CompositionConstants.ExportTypeIdentityMetadataName),
- CreateMetadataValueEqualsExpression(parameter, requiredTypeIdentity, CompositionConstants.ExportTypeIdentityMetadataName));
- }
-
- private static Expression CreateMetadataContainsKeyExpression(ParameterExpression parameter, string constantKey)
- {
- Assumes.NotNull(parameter, constantKey);
-
- // definition.Metadata.ContainsKey(constantKey)
- return Expression.Call(
- Expression.Property(parameter, ConstraintServices._exportDefinitionMetadataProperty),
- ConstraintServices._metadataContainsKeyMethod,
- Expression.Constant(constantKey));
- }
-
- private static Expression CreateMetadataOfTypeExpression(ParameterExpression parameter, string constantKey, Type constantType)
- {
- Assumes.NotNull(parameter, constantKey);
- Assumes.NotNull(parameter, constantType);
-
- // constantType.IsInstanceOfType(definition.Metadata[constantKey])
- return Expression.Call(
- Expression.Constant(constantType, typeof(Type)),
- ConstraintServices._typeIsInstanceOfTypeMethod,
- Expression.Call(
- Expression.Property(parameter, ConstraintServices._exportDefinitionMetadataProperty),
- ConstraintServices._metadataItemMethod,
- Expression.Constant(constantKey))
- );
- }
-
- private static Expression CreateMetadataValueEqualsExpression(ParameterExpression parameter, object constantValue, string metadataName)
- {
- Assumes.NotNull(parameter, constantValue);
-
- // constantValue.Equals(definition.Metadata[CompositionServices.PartCreationPolicyMetadataName])
- return Expression.Call(
- Expression.Constant(constantValue),
- ConstraintServices._metadataEqualsMethod,
- Expression.Call(
- Expression.Property(parameter, ConstraintServices._exportDefinitionMetadataProperty),
- ConstraintServices._metadataItemMethod,
- Expression.Constant(metadataName)));
- }
-
- public static Expression<Func<ExportDefinition, bool>> CreatePartCreatorConstraint(Expression<Func<ExportDefinition, bool>> baseConstraint, ImportDefinition productImportDefinition)
- {
- ParameterExpression exportDefinitionParameter = baseConstraint.Parameters[0];
-
- // exportDefinition.Metadata
- Expression metadataExpression = Expression.Property(exportDefinitionParameter, ConstraintServices._exportDefinitionMetadataProperty);
-
- // exportDefinition.Metadata.ContainsKey("ProductDefinition")
- Expression containsProductExpression = Expression.Call(
- metadataExpression,
- ConstraintServices._metadataContainsKeyMethod,
- Expression.Constant(CompositionConstants.ProductDefinitionMetadataName));
-
- // exportDefinition.Metadata["ProductDefinition"]
- Expression productExportDefinitionExpression = Expression.Call(
- metadataExpression,
- ConstraintServices._metadataItemMethod,
- Expression.Constant(CompositionConstants.ProductDefinitionMetadataName));
-
- // ProductImportDefinition.Contraint((ExportDefinition)exportDefinition.Metadata["ProductDefinition"])
- Expression productMatchExpression =
- Expression.Invoke(productImportDefinition.Constraint,
- Expression.Convert(productExportDefinitionExpression, typeof(ExportDefinition)));
-
- // baseContraint(exportDefinition) &&
- // exportDefinition.Metadata.ContainsKey("ProductDefinition") &&
- // ProductImportDefinition.Contraint((ExportDefinition)exportDefinition.Metadata["ProductDefinition"])
- Expression<Func<ExportDefinition, bool>> constraint =
- Expression.Lambda<Func<ExportDefinition, bool>>(
- Expression.AndAlso(
- baseConstraint.Body,
- Expression.AndAlso(
- containsProductExpression,
- productMatchExpression)),
- exportDefinitionParameter);
-
- return constraint;
- }
- }
- }