public override ServiceModel Reflect() { var descriptions = configuration.Services.GetApiExplorer().ApiDescriptions.AsEnumerable() .Where(c => !c.ActionDescriptor.GetCustomAttributes<FickleExcludeAttribute>().Any()) .ToList(); if (this.options.ControllersTypesToIgnore != null) { descriptions = descriptions.Where(x => !this.options.ControllersTypesToIgnore.Contains(x.ActionDescriptor.ControllerDescriptor.ControllerType)).ToList(); } bool secureByDefault = false; var enums = new List<ServiceEnum>(); var classes = new List<ServiceClass>(); var gateways = new List<ServiceGateway>(); var referencedTypes = GetReferencedTypes(descriptions).ToList(); var controllers = descriptions.Select(c => c.ActionDescriptor.ControllerDescriptor).ToHashSet(); var serviceModelInfo = new ServiceModelInfo(); foreach (var enumType in referencedTypes.Where(c => c.BaseType == typeof(Enum))) { var serviceEnum = new ServiceEnum { Name = GetTypeName(enumType), Values = Enum.GetNames(enumType).Select(c => new ServiceEnumValue { Name = c, Value = Convert.ToInt64(Enum.Parse(enumType, c)) }).ToList() }; enums.Add(serviceEnum); } foreach (var type in referencedTypes .Where(TypeSystem.IsNotPrimitiveType) .Where(c => c.BaseType != typeof(Enum)) .Where(c => !c.IsInterface) .Where(c => !typeof(IList<>).IsAssignableFromIgnoreGenericParameters(c))) { var baseTypeName = GetTypeName(type.BaseType); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Where(c => !c.GetCustomAttributes<FickleExcludeAttribute>().Any()) .Select(c => new ServiceProperty { Name = c.Name, TypeName = GetTypeName(c.PropertyType) }).ToList(); var serviceClass = new ServiceClass { Name = GetTypeName(type), BaseTypeName = baseTypeName, Properties = properties }; classes.Add(serviceClass); } var allowedMethods = new HashSet<string>(new[] { "GET", "POST" }, StringComparer.InvariantCultureIgnoreCase); foreach (var controller in controllers) { var methods = new List<ServiceMethod>(); secureByDefault = this.referencingAssembly.GetCustomAttributes<FickleSecureAttribute>()?.FirstOrDefault()?.Secure ?? false; var controllerSecureByDefault = controller.GetCustomAttributes<FickleSecureAttribute>(true)?.FirstOrDefault()?.Secure ?? secureByDefault; var serviceNameSuffix = "Service"; var attribute = this.referencingAssembly.GetCustomAttribute<FickleSdkInfoAttribute>(); if (attribute != null) { serviceNameSuffix = attribute.ServiceNameSuffix ?? serviceNameSuffix; serviceModelInfo.Name = attribute.Name ?? serviceModelInfo.Name; serviceModelInfo.Summary = attribute.Summary ?? serviceModelInfo.Summary; serviceModelInfo.Author = attribute.Author ?? serviceModelInfo.Author; serviceModelInfo.Version = attribute.Version ?? serviceModelInfo.Version; } foreach (var api in descriptions .Where(c => c.ActionDescriptor.ControllerDescriptor == controller && allowedMethods.Contains(c.HttpMethod.Method))) { var formatters = api.ActionDescriptor.ControllerDescriptor.Configuration.Formatters; var returnType = api.ResponseDescription.ResponseType ?? api.ResponseDescription.DeclaredType; if (!formatters.Any(c => c is JsonMediaTypeFormatter)) { returnType = typeof(string); } var parameters = api.ParameterDescriptions.Select(d => new ServiceParameter { Name = d.ParameterDescriptor.ParameterName, TypeName = GetTypeName(d.ParameterDescriptor.ParameterType) }).ToList(); ServiceParameter contentServiceParameter = null; var contentParameter = api.ParameterDescriptions.SingleOrDefault(c => c.Source == ApiParameterSource.FromBody); var uniqueNameMaker = new UniqueNameMaker(c => api.ParameterDescriptions.Any(d => d.Name.EqualsIgnoreCase(c))); if (contentParameter == null && api.HttpMethod.Method.EqualsIgnoreCaseInvariant("POST") && api.ActionDescriptor.GetCustomAttributes<NoBodyAttribute>().Count == 0) { contentServiceParameter = new ServiceParameter { Name = uniqueNameMaker.Make("content"), TypeName = GetTypeName(typeof(byte[])) }; parameters.Add(contentServiceParameter); } else if (contentParameter != null) { contentServiceParameter = new ServiceParameter { Name = contentParameter.Name, TypeName = GetTypeName(contentParameter.ParameterDescriptor.ParameterType) }; } var serviceMethod = new ServiceMethod { Authenticated = api.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>(true).Count > 0, Secure = api.ActionDescriptor.GetCustomAttributes<FickleSecureAttribute>(true)?.FirstOrDefault()?.Secure ?? controllerSecureByDefault, Name = api.ActionDescriptor.ActionName, Path = StringUriUtils.Combine(this.configuration.VirtualPathRoot, api.RelativePath), Returns = GetTypeName(returnType), ReturnFormat = "json", Method = api.HttpMethod.Method.ToLower(), Parameters = parameters }; if (contentServiceParameter != null) { serviceMethod.Content = contentServiceParameter.Name; serviceMethod.ContentServiceParameter = contentServiceParameter; } methods.Add(serviceMethod); } var serviceGateway = new ServiceGateway { BaseTypeName = null, Name = controller.ControllerName + serviceNameSuffix, Hostname = hostname, Methods = methods }; gateways.Add(serviceGateway); } return new ServiceModel(serviceModelInfo, enums, classes, gateways); }
protected virtual ServiceParameter ProcessParameter() { var retval = new ServiceParameter() { Name = this.tokenizer.CurrentIdentifier }; this.ReadNextToken(); this.Expect(FicklefileToken.Colon); this.ReadNextToken(); this.Expect(FicklefileToken.Identifier); retval.TypeName = this.tokenizer.CurrentIdentifier; this.ReadNextToken(); if (this.tokenizer.CurrentToken == FicklefileToken.QuestionMark) { retval.TypeName += "?"; this.ReadNextToken(); } if (this.tokenizer.CurrentToken == FicklefileToken.OpenBracket) { this.ReadNextToken(); this.Expect(FicklefileToken.CloseBracket); this.ReadNextToken(); retval.TypeName += "[]"; } return retval; }
public virtual Expression Build(ServiceParameter parameter) { return Expression.Parameter(this.GetTypeFromName(parameter.TypeName), parameter.Name); }