public override LambdaExpression VisitAttrPath(ScimFilterParser.AttrPathContext context) { string schemaToken = GetSchema(context); if (!string.IsNullOrEmpty(schemaToken) && ServerConfiguration.ResourceExtensionExists(schemaToken)) { return(VisitResourceExtensionAttrPath(context)); } if (!string.IsNullOrEmpty(schemaToken)) // fully qualified property { string schemaIdentifierForResourceType = ServerConfiguration.GetSchemaIdentifierForResourceType(typeof(TResource)); // swallow correct namespace but validate if (!string.Equals(schemaToken, schemaIdentifierForResourceType, StringComparison.OrdinalIgnoreCase)) { throw new Exception("unrecognized schema"); // TODO: (MR) make proper error } } string propNameToken = context.ATTRNAME(0).GetText(); var argument = Expression.Parameter(typeof(TResource)); PropertyInfo propertyInfo = GetPropertyInfoFromCache(typeof(TResource), propNameToken); return(Expression.Lambda(Expression.Property(argument, propertyInfo), argument)); }
public virtual LambdaExpression VisitResourceExtensionAttrPath(ScimFilterParser.AttrPathContext context) { /* We want to achieve something like this below * Func<TResource, e.g. EnterpriseUserExtension.Manager.GetType()> lambda = r => r.Extensions * .Select(k => k.Value) * .OfType<EnterpriseUserExtension>() * .Select(e => e.Manager) * .FirstOrDefault(); */ var argument = Expression.Parameter(typeof(TResource)); string propNameToken = context.ATTRNAME(0).GetText(); string schemaToken = GetSchema(context); Type extensionType = ServerConfiguration.ResourceExtensionSchemas[schemaToken]; PropertyInfo extensionsPropInfo = GetPropertyInfoFromCache(typeof(TResource), "Extensions"); var extensionPropertyExpression = Expression.Property(argument, extensionsPropInfo); var keyValuePairArgument = Expression.Parameter(typeof(KeyValuePair <string, ResourceExtension>)); var selectExtensionExpression = Expression.Call( typeof(Enumerable), "Select", new[] { typeof(KeyValuePair <string, ResourceExtension>), typeof(ResourceExtension) }, extensionPropertyExpression, Expression.Lambda <Func <KeyValuePair <string, ResourceExtension>, ResourceExtension> >( Expression.Property(keyValuePairArgument, "Value"), keyValuePairArgument)); var selectTypedExtensionExpression = Expression.Call( typeof(Enumerable), "OfType", new[] { extensionType }, selectExtensionExpression); PropertyInfo propertyInfo = GetPropertyInfoFromCache(extensionType, propNameToken); var extensionArgument = Expression.Parameter(extensionType); var selectTypedExtensionPropertyExpression = Expression.Call( typeof(Enumerable), "Select", new[] { extensionType, propertyInfo.PropertyType }, selectTypedExtensionExpression, MakeLambdaExpression(extensionType, propertyInfo.PropertyType, Expression.Property(extensionArgument, propertyInfo), extensionArgument)); var firstExpression = Expression.Call( typeof(Enumerable), "FirstOrDefault", new[] { propertyInfo.PropertyType }, selectTypedExtensionPropertyExpression); return(MakeLambdaExpression(typeof(TResource), propertyInfo.PropertyType, firstExpression, argument)); }