상속: StructuredType
예제 #1
0
 public ResourceProperty(IResourceTypeResolver typeResolver,
                         PropertyInfo propertyInfo,
                         ResourceType reflectedType)
     : base(typeResolver, propertyInfo, reflectedType)
 {
     this.resourcePropertyDetails = CreateLazy(() => typeResolver.LoadResourcePropertyDetails(this));
 }
예제 #2
0
 protected virtual Func<PomonaContext, PomonaResponse> ResolveGetCollection(Route route,
                                                                            ResourceType resourceType)
 {
     var propertyRoute = route as ResourcePropertyRoute;
     if (propertyRoute != null)
         return ResolveGetCollectionProperty(propertyRoute, propertyRoute.Property, resourceType);
     return null;
 }
예제 #3
0
 public DataSourceCollectionRoute(DataSourceRootRoute parent, ResourceType resultItemType)
     : base(0, parent)
 {
     if (resultItemType == null)
         throw new ArgumentNullException(nameof(resultItemType));
     this.parent = parent;
     this.resultItemType = resultItemType;
     ResultType = parent.TypeMapper.FromType(typeof(IEnumerable<>).MakeGenericType(resultItemType));
 }
예제 #4
0
 public GetByIdRoute(ResourceType resultItemType, Route parent, HttpMethod allowedMethods)
     : base(10, parent)
 {
     if (resultItemType == null)
         throw new ArgumentNullException(nameof(resultItemType));
     this.resultItemType = resultItemType;
     AllowedMethods = allowedMethods;
     IdProperty = this.resultItemType.PrimaryId;
     if (IdProperty == null)
         throw new ArgumentException("Resource in collection needs to have a primary id.");
 }
예제 #5
0
 private RouteAction MatchCollectionNodeRequest(HttpMethod method, ResourceType resourceType)
 {
     switch (method)
     {
         case HttpMethod.Post:
             return NameStartsWith(method) ? MatchMethodTakingForm(resourceType) : null;
         case HttpMethod.Get:
             return MatchMethodReturningQueryable(resourceType);
     }
     return null;
 }
 private static Func<PomonaContext, PomonaResponse> ResolvePatch(Route route, ResourceType resourceItemType)
 {
     if (route.IsSingle)
     {
         return pr =>
         {
             var patchedObject = pr.Bind();
             var dataSource = GetDataSource(pr.Session);
             var patchedType = patchedObject.GetType();
             return new PomonaResponse(pr, dataSource.Patch(patchedType, patchedObject));
         };
     }
     return null;
 }
예제 #7
0
 protected virtual Func<PomonaContext, PomonaResponse> ResolveGetById(GetByIdRoute route,
                                                                      ResourceType resourceType)
 {
     var idProp = route.IdProperty;
     var idType = idProp.PropertyType;
     return pr =>
     {
         var segmentValue = pr.Node.PathSegment.Parse(idType);
         var segmentExpression = Ex.Const(segmentValue, idType);
         var whereExpression = pr.Node.Parent
                                 .Query()
                                 .WhereEx(ex => ex.Apply(idProp.CreateGetterExpression) == segmentExpression);
         var queryableResult = whereExpression.WrapActionResult(QueryProjection.FirstOrDefault);
         return new PomonaResponse(pr, queryableResult);
     };
 }
예제 #8
0
 public ResourceTypeDetails(ResourceType type,
     string uriRelativePath,
     bool isExposedAsRepository,
     Type postReturnType,
     PropertyInfo parentToChildPropertyInfo,
     PropertyInfo childToParentPropertyInfo)
 {
     if (type == null)
         throw new ArgumentNullException("type");
     this.type = type;
     this.uriRelativePath = uriRelativePath;
     this.isExposedAsRepository = isExposedAsRepository;
     this.postReturnType = postReturnType;
     this.parentToChildPropertyInfo = parentToChildPropertyInfo;
     this.childToParentPropertyInfo = childToParentPropertyInfo;
 }
예제 #9
0
 public ResourceNode(ITypeMapper typeMapper,
     PathNode parent,
     string name,
     Func<object> valueFetcher,
     ResourceType expectedType)
     : base(typeMapper, parent, name)
 {
     this.value = new System.Lazy<object>(valueFetcher);
     this.expectedType = expectedType;
     this.type = new System.Lazy<ResourceType>(() =>
     {
         var localValue = Value;
         if (Value == null)
             return expectedType;
         return (ResourceType)typeMapper.GetClassMapping(localValue.GetType());
     });
 }
예제 #10
0
        protected virtual Func<PomonaContext, PomonaResponse> ResolveGetCollectionProperty(ResourcePropertyRoute route,
                                                                                           ResourceProperty property,
                                                                                           ResourceType resourceItemType)
        {
            if (this.capabilityResolver.PropertyIsMapped(property.PropertyInfo) || property.GetPropertyFormula() != null)
            {
                return
                    pr =>
                    {
                        // Check existance of parent here, cannot differentiate between an empty collection and not found.
                        var parent = pr.Node.Parent;
                        if (parent.Route.IsSingle)
                        {
                            if (!parent.Exists)
                                throw new ResourceNotFoundException("Resource not found.");
                        }

                        return new PomonaResponse(
                            parent
                                .Query()
                                .OfTypeIfRequired(pr.Node.Route.InputType)
                                .SelectManyEx(x => x.Apply(property.CreateGetterExpression))
                                .WrapActionResult(defaultPageSize : property.ExposedAsRepository ? (int?)null : int.MaxValue));
                    };
            }
            else
            {
                return
                    pr =>
                    {
                        var parentNode = pr.Node.Parent;
                        if (parentNode.Route.IsSingle)
                            return new PomonaResponse(((IEnumerable)property.GetValue(parentNode.Get())).AsQueryable());
                        return new PomonaResponse(
                            pr.Node.Parent
                              .Query()
                              .OfTypeIfRequired(pr.Node.Route.InputType)
                              .ToListDetectType()
                              .AsQueryable()
                              .SelectManyEx(x => x.Apply(property.CreateGetterExpression))
                              .WrapActionResult(defaultPageSize : property.ExposedAsRepository ? (int?)null : int.MaxValue));
                    };
            }
        }
예제 #11
0
        private static Func<PomonaContext, PomonaResponse> ResolveGetCollection(Route route, ResourceType resourceType)
        {
            var dataSourceCollectionRoute = route as DataSourceCollectionRoute;
            if (dataSourceCollectionRoute != null)
            {
                return pr =>
                {
                    Type[] qTypeArgs;
                    var elementType = resourceType.Type;
                    if (pr.AcceptType != null
                        && pr.AcceptType.TryExtractTypeArguments(typeof(IQueryable<>), out qTypeArgs))
                        elementType = qTypeArgs[0];

                    var dataSource = GetDataSource(pr.Session);
                    var entity = dataSource.Query(elementType);
                    return new PomonaResponse(pr, entity);
                };
            }
            return null;
        }
예제 #12
0
 public ResourceTypeDetails(ResourceType type,
                            string urlRelativePath,
                            bool isExposedAsRepository,
                            Type postReturnType,
                            PropertyInfo parentToChildPropertyInfo,
                            PropertyInfo childToParentPropertyInfo,
                            bool isSingleton,
                            IEnumerable<Type> resourceHandlers,
                            string pluralName)
 {
     if (type == null)
         throw new ArgumentNullException(nameof(type));
     this.type = type;
     UrlRelativePath = urlRelativePath;
     IsExposedAsRepository = isExposedAsRepository;
     this.postReturnType = postReturnType;
     this.parentToChildPropertyInfo = parentToChildPropertyInfo;
     this.childToParentPropertyInfo = childToParentPropertyInfo;
     IsSingleton = isSingleton;
     ResourceHandlers = resourceHandlers;
     PluralName = pluralName;
 }
예제 #13
0
파일: TypeMapper.cs 프로젝트: Pomona/Pomona
 public override ResourceType LoadUriBaseType(ResourceType resourceType)
 {
     Type uriBaseType = Filter.GetUriBaseType(resourceType.Type);
     return uriBaseType != null ? (ResourceType)FromType(uriBaseType) : null;
 }
예제 #14
0
 public abstract ResourceTypeDetails LoadResourceTypeDetails(ResourceType resourceType);
예제 #15
0
        private void RegisterRoutesFor(ResourceType type)
        {
            var path = "/" + type.UriRelativePath;

            Register(Get, path + "/{remaining*}", x => GetResource());
            Register(Get, path, x => GetResource());
            Register(Post, path, x => GetResource());
            Register(Patch, path + "/{remaining*}", x => GetResource());
            Register(Post, path + "/{remaining*}", x => GetResource());
        }
예제 #16
0
 private static Func<PomonaContext, PomonaResponse> ResolvePost(Route route, ResourceType resourceItemType)
 {
     if (route.NodeType == PathNodeType.Collection)
         return ResolvePostToCollection(route, resourceItemType);
     return null;
 }
예제 #17
0
 private static Func<PomonaContext, PomonaResponse> ResolvePostToCollection(Route route, ResourceType resourceItemType)
 {
     if (route.ResultItemType is ResourceType
         && route.ResultType.IsCollection
         && route.Root() is DataSourceRootRoute)
     {
         return pr =>
         {
             var form = pr.Bind(resourceItemType);
             var dataSource = GetDataSource(pr.Session);
             var entity = dataSource.Post(form.GetType(), form);
             return new PomonaResponse(pr, entity);
         };
     }
     return null;
 }
예제 #18
0
        private RouteAction MatchResourceNodeRequest(HttpMethod httpMethod, ResourceType resourceType)
        {
            if (!NameStartsWith(httpMethod))
                return null;

            switch (httpMethod)
            {
                case HttpMethod.Delete:
                    return MatchMethodTakingExistingResource(resourceType);
                case HttpMethod.Patch:
                    return MatchMethodTakingPatchedExistingResource(resourceType);
                case HttpMethod.Get:
                    return MatchMethodTakingResourceId(resourceType);
                case HttpMethod.Post:
                    return MatchMethodTakingExistingResourceAndForm(resourceType);
            }
            return null;
        }
예제 #19
0
        private RouteAction MatchMethodTakingResourceId(ResourceType resourceType)
        {
            if (MethodInfo.ReturnType != resourceType.Type)
                return null;

            var idParam = Parameters.SingleOrDefault(x => x.Type == resourceType.PrimaryId.PropertyType.Type);
            if (idParam != null)
                return new HandlerMethodTakingResourceId(this);
            return null;
        }
예제 #20
0
        private RouteAction MatchMethodReturningQueryable(ResourceType resourceType)
        {
            // Check that the method is called "Get", "Query", "Get<TypeName>s" or "Query<TypeName>s".
            if (!MethodInfo.Name.Equals("Get") && !MethodInfo.Name.Equals("Query") &&
                !MethodInfo.Name.Equals("Get" + resourceType.PluralName) &&
                !MethodInfo.Name.Equals("Query" + resourceType.PluralName))
                return null;

            // Check that the it takes a parameter of type Parent if the type is a child resource of Parent.
            if (resourceType.ParentResourceType != null)
            {
                var parentParameter = MethodInfo.GetParameters();
                if (parentParameter.Length != 1 ||
                    parentParameter[0].ParameterType != resourceType.ParentResourceType.Type)
                    return null;
            }

            // Check that it returns an IQueryable<Object>.
            if (!typeof(IQueryable<>).MakeGenericType(resourceType.Type).IsAssignableFrom(MethodInfo.ReturnType))
                return null;

            return new DefaultHandlerMethodInvoker(this);
        }
예제 #21
0
 private static Func<PomonaContext, PomonaResponse> ResolveGet(Route route, ResourceType resourceType)
 {
     if (route.ResultType.IsCollection)
         return ResolveGetCollection(route, resourceType);
     return null;
 }
예제 #22
0
        protected virtual Func<PomonaContext, PomonaResponse> ResolveGetSingle(Route route, ResourceType resourceType)
        {
            var getByIdRoute = route as GetByIdRoute;
            if (getByIdRoute != null && !getByIdRoute.IsRoot)
                return ResolveGetById(getByIdRoute, resourceType);

            var propertyRoute = route as ResourcePropertyRoute;
            if (propertyRoute != null)
                return ResolveGetSingleProperty(propertyRoute, propertyRoute.Property, resourceType);

            return null;
        }
예제 #23
0
 protected virtual Func<PomonaContext, PomonaResponse> ResolveGetSingleProperty(ResourcePropertyRoute route,
                                                                                StructuredProperty property,
                                                                                ResourceType resourceType)
 {
     return
         pr =>
             new PomonaResponse(pr,
                                pr.Node.Parent.Query()
                                  .SelectEx(x => x.Apply(property.CreateGetterExpression))
                                  .WrapActionResult(QueryProjection.FirstOrDefault));
 }
예제 #24
0
        private static void BuildUriGenerator(ResourceType rt,
                                              List<Expression> sbFormatArgs,
                                              Expression parentExpression,
                                              StringBuilder formatStringBuilder)
        {
            if (rt.PrimaryId == null)
                throw new InvalidOperationException($"{rt.Name} has no Id property or primary key mapping");

            var parentToChildProperty = rt.ParentToChildProperty;
            if (parentToChildProperty != null)
            {
                var childToParentProperty = rt.ChildToParentProperty;
                var nextParentExpr = childToParentProperty.CreateGetterExpression(parentExpression);
                BuildUriGenerator(rt.ParentResourceType, sbFormatArgs, nextParentExpr, formatStringBuilder);
                if (formatStringBuilder.Length > 0)
                    formatStringBuilder.Append('/');
                formatStringBuilder.AppendFormat("{0}", parentToChildProperty.UriName);
                if (parentToChildProperty.PropertyType.IsCollection)
                {
                    formatStringBuilder.AppendFormat("/{{{0}}}", sbFormatArgs.Count);
                    var sbArgsExpr = rt.PrimaryId.CreateGetterExpression(parentExpression);
                    sbFormatArgs.Add(sbArgsExpr);
                }
            }
            else
            {
                if (rt.IsSingleton)
                    formatStringBuilder.AppendFormat("{0}", rt.UrlRelativePath);
                else
                {
                    var sbArgsExpr = rt.PrimaryId.CreateGetterExpression(parentExpression);
                    formatStringBuilder.AppendFormat("{0}/{{{1}}}", rt.UrlRelativePath, sbFormatArgs.Count);
                    sbFormatArgs.Add(sbArgsExpr);
                }
            }
        }
예제 #25
0
 protected virtual Func<PomonaContext, PomonaResponse> ResolveGet(Route route, ResourceType resourceType)
 {
     if (route.ResultType.IsCollection)
         return ResolveGetCollection(route, resourceType);
     return ResolveGetSingle(route, resourceType);
 }
예제 #26
0
파일: TypeMapper.cs 프로젝트: Pomona/Pomona
        public override ResourceTypeDetails LoadResourceTypeDetails(ResourceType resourceType)
        {
            var type = resourceType.Type;
            var parentToChildProperty = Filter.GetParentToChildProperty(type);
            var childToParentProperty = Filter.GetChildToParentProperty(type);
            var isRootResource = parentToChildProperty == null;

            var relativeResourcePath = isRootResource ? Filter.GetUrlRelativePath(type).TrimStart('/') : null;

            return new ResourceTypeDetails(resourceType,
                                           relativeResourcePath,
                                           Filter.TypeIsExposedAsRepository(type),
                                           Filter.GetPostReturnType(type),
                                           parentToChildProperty,
                                           childToParentProperty,
                                           Filter.TypeIsSingletonResource(type),
                                           Filter.GetResourceHandlers(type),
                                           Filter.GetPluralNameForType(type));
        }
예제 #27
0
        private static Expression<Action<object, StringBuilder>> BuildUriGenerator(ResourceType rt)
        {
            var parameterExpression = Expression.Parameter(typeof(object), "x");
            var objParam = Expression.Convert(parameterExpression, rt);
            var sbParam = Expression.Parameter(typeof(StringBuilder), "sb");
            var sbArgs = new List<Expression>();
            var formatStringBuilder = new StringBuilder();
            BuildUriGenerator(rt, sbArgs, objParam, formatStringBuilder);
            var sbArgsEncoded =
                sbArgs.Select(
                    GetUrlPathEncodedExpression);

            return Expression.Lambda<Action<object, StringBuilder>>(Expression.Call(sbParam,
                                                                                    stringBuilderAppendFormatMethod,
                                                                                    Expression.Constant(CultureInfo.InvariantCulture),
                                                                                    Expression.Constant(formatStringBuilder.ToString()),
                                                                                    Expression.NewArrayInit(typeof(object), sbArgsEncoded)),
                                                                    parameterExpression,
                                                                    sbParam);
        }
예제 #28
0
 private static void BuildUriGenerator(ResourceType rt,
     List<Expression> sbFormatArgs,
     Expression parentExpression,
     StringBuilder formatStringBuilder)
 {
     if (rt.ParentToChildProperty != null)
     {
         var nextParentExpr = rt.ChildToParentProperty.CreateGetterExpression(parentExpression);
         BuildUriGenerator(rt.ParentResourceType, sbFormatArgs, nextParentExpr, formatStringBuilder);
         var sbArgsExpr = rt.PrimaryId.CreateGetterExpression(parentExpression);
         formatStringBuilder.AppendFormat("/{0}/{{{1}}}", rt.ParentToChildProperty.UriName, sbFormatArgs.Count);
         sbFormatArgs.Add(sbArgsExpr);
     }
     else
     {
         var sbArgsExpr = rt.PrimaryId.CreateGetterExpression(parentExpression);
         formatStringBuilder.AppendFormat("{0}/{{{1}}}", rt.UriRelativePath, sbFormatArgs.Count);
         sbFormatArgs.Add(sbArgsExpr);
     }
 }
예제 #29
0
        private void AddRepositoryFormPostMethod(MethodAttributes methodAttributes,
            bool isImplementation,
            ResourceType subType,
            TypeDefinition repoTypeDef,
            TypeDefinition baseTypeGenericDef,
            TypeReference[] baseTypeGenericArgs)
        {
            var postReturnTypeRef = this.clientTypeInfoDict[subType.PostReturnType].InterfaceType;
            var method = new MethodDefinition("Post",
                methodAttributes,
                postReturnTypeRef);
            method.Parameters.Add(new ParameterDefinition("form", 0, this.clientTypeInfoDict[subType].PostFormType));
            repoTypeDef.Methods.Add(method);

            if (isImplementation)
            {
                var basePostMethodRef =
                    Import(
                        Import(typeof(ClientRepository<,>)).Resolve().GetMethods()
                            .Single(
                                x =>
                                    x.Name == "Post" && x.Parameters.Count == 1 &&
                                    x.Parameters[0].Name == "form")
                        ).MakeHostInstanceGeneric(baseTypeGenericArgs);

                var ilproc = method.Body.GetILProcessor();

                ilproc.Emit(OpCodes.Ldarg_0);
                ilproc.Emit(OpCodes.Ldarg_1);

                ilproc.Emit(OpCodes.Callvirt, basePostMethodRef);

                ilproc.Emit(OpCodes.Castclass, postReturnTypeRef);
                ilproc.Emit(OpCodes.Ret);
            }
        }
예제 #30
0
 private static void BuildUriTemplate(ResourceType rt,
     StringBuilder sb,
     string parentPath,
     bool useJsonNameStyle = false)
 {
     if (rt.ParentToChildProperty != null)
     {
         BuildUriTemplate(rt.ParentResourceType,
             sb,
             string.Format("{0}{1}.",
                 parentPath,
                 useJsonNameStyle ? rt.ChildToParentProperty.Name : rt.ChildToParentProperty.JsonName));
         sb.AppendFormat("/{0}/{{{1}{2}}}",
             rt.ParentToChildProperty.UriName,
             parentPath,
             rt.PrimaryId.Name);
     }
     else
         sb.AppendFormat("{0}/{{{1}{2}}}", rt.UriRelativePath, parentPath, rt.PrimaryId.Name);
 }