Esempio n. 1
0
        /// <summary>
        /// All types covered by RESTable are selected and validated here
        ///
        /// Resources
        ///   entity
        ///     regular
        ///     wrapper
        ///   terminal
        ///   binary
        /// Views
        ///
        /// </summary>
        /// <returns></returns>
        private void ValidateAndBuildTypeLists(out List <Type> regularTypes, out List <Type> wrapperTypes, out List <Type> terminalTypes,
                                               out List <Type> binaryTypes, out List <Type> eventTypes)
        {
            var allTypes      = typeof(object).GetSubclasses().ToList();
            var resourceTypes = allTypes.Where(t => t.HasAttribute <RESTableAttribute>(out var a) && a is not RESTableProceduralAttribute).ToArray();
            var viewTypes     = allTypes.Where(t => t.HasAttribute <RESTableViewAttribute>()).ToArray();

            if (resourceTypes.Union(viewTypes).ContainsDuplicates(t => t.GetRESTableTypeName()?.ToLower() ?? "unknown", out var dupe))
            {
                throw new InvalidResourceDeclarationException("Types used by RESTable must have unique case insensitive names. Found " +
                                                              $"multiple types with case insensitive name '{dupe}'.");
            }

            void ValidateViewTypes(ICollection <Type> _viewTypes)
            {
                foreach (var viewType in _viewTypes)
                {
                    var resource = viewType.DeclaringType;
                    if (!viewType.IsClass || !viewType.IsNestedPublic || resource == null)
                    {
                        throw new InvalidResourceViewDeclarationException(viewType,
                                                                          "Resource view types must be declared as public classes nested within the the " +
                                                                          "resource type they are views for");
                    }
                    if (viewType.IsSubclassOf(resource))
                    {
                        throw new InvalidResourceViewDeclarationException(viewType, "Views cannot inherit from their resource types");
                    }
                    if (typeof(IResourceWrapper).IsAssignableFrom(resource))
                    {
                        var wrapped = resource.GetWrappedType();
                        if (!viewType.ImplementsGenericInterface(typeof(ISelector <>), out var param) || param[0] != wrapped)
                        {
                            throw new InvalidResourceViewDeclarationException(viewType,
                                                                              $"Expected view type to implement ISelector<{wrapped.GetRESTableTypeName()}>");
                        }
                    }
                    else if (!viewType.ImplementsGenericInterface(typeof(ISelector <>), out var param) || param[0] != resource)
                    {
                        throw new InvalidResourceViewDeclarationException(viewType,
                                                                          $"Expected view type to implement ISelector<{resource.GetRESTableTypeName()}>");
                    }
                    var resourceProperties = TypeCache.GetDeclaredProperties(resource);
                    foreach (var property in TypeCache.FindAndParseDeclaredProperties(viewType).Where(prop => resourceProperties.ContainsKey(prop.Name)))
                    {
                        throw new InvalidResourceViewDeclarationException(viewType,
                                                                          $"Invalid property '{property.Name}'. Resource view types must not contain any public instance " +
                                                                          "properties with the same name (case insensitive) as a property of the corresponding resource. " +
                                                                          "All properties in the resource are automatically inherited for use in conditions with the view.");
                    }
                }
            }

            (regularTypes, wrapperTypes, terminalTypes, binaryTypes, eventTypes) = ResourceValidator.Validate(resourceTypes);
            ValidateViewTypes(viewTypes);
        }
Esempio n. 2
0
 public ResourceFactory
 (
     IEnumerable <IEntityResourceProvider> resourceProviders,
     TerminalResourceProvider terminalResourceProvider,
     BinaryResourceProvider binaryResourceProvider,
     VirtualResourceProvider virtualResourceProvider,
     TypeCache typeCache,
     ResourceValidator resourceValidator,
     ResourceCollection resourceCollection,
     RootAccess rootAccess
 )
 {
     TerminalProvider          = terminalResourceProvider;
     BinaryProvider            = binaryResourceProvider;
     VrProvider                = virtualResourceProvider;
     ExternalResourceProviders = resourceProviders.ToList();
     TypeCache               = typeCache;
     ResourceValidator       = resourceValidator;
     ResourceCollection      = resourceCollection;
     RootAccess              = rootAccess;
     EntityResourceProviders = new Dictionary <string, IEntityResourceProviderInternal>();
 }