public void Read(ConfigurationBase configurationBase, List <ITransferObject> transferObjects) { ReflectionReadConfiguration configuration = (ReflectionReadConfiguration)configurationBase; Type type = GeneratorTypeLoader.Get(configuration, configuration.Assembly, configuration.Namespace, configuration.Name); if (type != null) { ModelTransferObject selfModel = this.modelReader.Read(type, transferObjects); if (configuration.SkipSelf) { transferObjects.Remove(selfModel); Logger.Trace($"{selfModel.Name} ({selfModel.Namespace}) skipped through configuration"); } } }
public void Read(ReflectionReadConfiguration configuration, IOptions caller = null) { Type type = GeneratorTypeLoader.Get(configuration.Assembly, configuration.Namespace, configuration.Name); if (type == null) { Logger.Trace($"Class {configuration.Namespace}.{configuration.Name} not found"); return; } ModelTransferObject selfModel = this.modelReader.Read(type, caller); IOptions modelOptions = this.options.Get(selfModel); if (configuration.OnlySubTypes || modelOptions.OnlySubTypes) { modelOptions.OnlySubTypes = true; } }
public override IGeneratorCommandResult Run() { Type type = GeneratorTypeLoader.Get(this.Parameters.Assembly, this.Parameters.Namespace, this.Parameters.Name); if (type == null) { Logger.Trace($"Class {this.Parameters.Namespace}.{this.Parameters.Name} not found"); return(this.Error()); } IOptions options = this.resolver.Get <Options>().Current; options.Language = this.resolver.Get <CsharpLanguage>(); SqliteModelTransferObject model = this.resolver.Create <SqliteModelReader>().Read(type); this.resolver.Get <IOutput>().DeleteAllRelatedFiles(this.Parameters.RelativePath); this.resolver.Create <SqliteRepositoryWriter>().Write(model, this.Parameters); return(this.Success()); }
public virtual void Read(AspDotNetReadConfiguration configuration) { configuration.Controller.AssertIsNotNull($"ASP: {nameof(configuration.Controller)}"); configuration.Controller.Name.AssertIsNotNull($"ASP: {nameof(configuration.Controller)}.{nameof(configuration.Controller.Name)}"); configuration.Controller.Namespace.AssertIsNotNull($"ASP: {nameof(configuration.Controller)}.{nameof(configuration.Controller.Namespace)}"); Logger.Trace($"Read ASP.NET controller {configuration.Controller.Namespace}.{configuration.Controller.Name}..."); Type type = GeneratorTypeLoader.Get(configuration.Controller.Assembly, configuration.Controller.Namespace, configuration.Controller.Name); if (type == null) { return; } HttpServiceTransferObject controller = new(); controller.Name = type.Name; controller.Language = ReflectionLanguage.Instance; IOptions typeOptions = this.options.Get(type); this.options.Set(controller, typeOptions); IAspDotNetOptions typeAspOptions = this.aspOptions.Get(type); this.aspOptions.Set(controller, typeAspOptions); controller.Route = typeAspOptions.Route; controller.Version = typeAspOptions.ApiVersion?.LastOrDefault(); List <MethodInfo> methods = new(); Type currentTyp = type; while (currentTyp?.Namespace != null && !currentTyp.Namespace.StartsWith("Microsoft") && !currentTyp.Namespace.StartsWith("System")) { IOptions currentOptions = this.options.Get(currentTyp); if (currentOptions.Ignore) { break; } methods.AddRange(currentTyp.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) // Remove all overwritten methods .Where(method => methods.All(m => m.GetBaseDefinition() != method)) ); currentTyp = currentTyp.BaseType; } foreach (MethodInfo method in methods) { IOptions methodOptions = this.options.Get(method); IAspDotNetOptions methodAspOptions = this.aspOptions.Get(method); if (methodOptions.Ignore || methodAspOptions.IsNonAction) { continue; } Dictionary <HttpServiceActionTypeTransferObject, string> actionTypes = this.GetActionTypes(methodAspOptions); if (actionTypes.Count == 0) { Logger.Error($"{type.FullName}.{method.Name} has to be decorated with at least one of [HttpGet], [HttpPost], [HttpPut], [HttpPatch], [HttpDelete], [NonAction] or with [GenerateIgnore]."); continue; } Type returnType = (methodAspOptions.Produces ?? method.ReturnType) .IgnoreGeneric("System.Threading.Tasks", "Task") .IgnoreGeneric("Microsoft.AspNetCore.Mvc", "IActionResult") .IgnoreGeneric("Microsoft.AspNetCore.Mvc", "ActionResult") .IgnoreGeneric("System.Web.Mvc", "ActionResult") .IgnoreGeneric("System.Web.Mvc", "ContentResult") .IgnoreGeneric("System.Web.Mvc", "EmptyResult") .IgnoreGeneric("System.Web.Mvc", "FileContentResult") .IgnoreGeneric("System.Web.Mvc", "FilePathResult") .IgnoreGeneric("System.Web.Mvc", "FileResult") .IgnoreGeneric("System.Web.Mvc", "FileStreamResult") .IgnoreGeneric("System.Web.Mvc", "JsonResult") .IgnoreGeneric(typeAspOptions.IgnoreGenerics) .IgnoreGeneric(methodAspOptions.IgnoreGenerics); Type returnEntryType = returnType.IgnoreGeneric(typeof(IEnumerable <>)).IgnoreGeneric(typeof(List <>)).IgnoreGeneric(typeof(IList <>)); IAspDotNetOptions returnEntryTypeOptions = this.aspOptions.Get(returnEntryType, methodAspOptions); foreach (KeyValuePair <HttpServiceActionTypeTransferObject, string> actionType in actionTypes) { HttpServiceActionTransferObject action = new(); action.Name = actionTypes.Count == 1 ? method.Name : $"{actionType.Key}{method.Name.FirstCharToUpper()}"; action.ReturnType = this.modelReader.Read(returnType, methodOptions); action.Route = actionType.Value ?? methodAspOptions.Route; if (action.Route?.Contains(":") ?? false) { action.Route = Regex.Replace(action.Route, "({[^:]*)((:apiVersion)|:[^}?]+)(\\??})", "$1$3$4"); } action.Type = actionType.Key; action.Version = methodAspOptions.ApiVersion?.OrderByDescending(x => x).FirstOrDefault(); action.FixCasingWithMapping = returnEntryTypeOptions.FixCasingWithMapping || methodAspOptions.FixCasingWithMapping; action.RequireBodyParameter = action.Type.IsBodyParameterRequired(); List <ParameterInfo> parameters = method.GetParameters().Where( parameter => !this.aspOptions.Get(parameter, methodAspOptions).IsFromHeader && !this.aspOptions.Get(parameter, methodAspOptions).IsFromServices && parameter.ParameterType.FullName != "System.Threading.CancellationToken" ).ToList(); foreach (ParameterInfo parameter in parameters) { IAspDotNetOptions parameterOptions = this.aspOptions.Get(parameter, methodAspOptions); string fullRoute = $"{controller.Route}/{action.Route}"; HttpServiceActionParameterTransferObject actionParameter = new(); actionParameter.Name = parameter.Name; actionParameter.Type = this.modelReader.Read(parameter.ParameterType, methodOptions); actionParameter.FromBody = parameterOptions.IsFromBody || action.Type != HttpServiceActionTypeTransferObject.Get && !parameter.ParameterType.IsValueType && parameter.ParameterType != typeof(string); actionParameter.FromQuery = parameterOptions.IsFromQuery; actionParameter.Inline = fullRoute.Contains($"{{{parameter.Name}}}"); actionParameter.InlineIndex = actionParameter.Inline && action.Route != null?action.Route.IndexOf($"{{{parameter.Name}}}") : 0; actionParameter.IsOptional = parameter.IsOptional; if (fullRoute.Contains($"{{{parameter.Name}?}}")) { actionParameter.Inline = true; actionParameter.IsOptional = true; actionParameter.InlineIndex = fullRoute.IndexOf($"{{{parameter.Name}?}}"); action.Route = action.Route.Replace($"{{{parameter.Name}?}}", $"{{{parameter.Name}}}"); } action.Parameters.Add(actionParameter); if (action.Type == HttpServiceActionTypeTransferObject.Get && actionParameter.Type.Name == "List" && !actionParameter.FromQuery) { Logger.Error($"HttpGet methods with list parameter '{parameter.Name}' of {type.FullName}.{method.Name} has to be decorated with [FromQuery]"); } } if (action.RequireBodyParameter) { if (action.Parameters.Count == 0) { throw new InvalidOperationException($"Can not write {method.Name}. {action.Type} requires at least one parameter, but no parameter found. Use [GenerateIgnore] to skip generation for that method"); } if (action.Parameters.Count == 1) { action.Parameters.Single().FromBody = true; } else if (action.Parameters.All(x => !x.FromBody)) { throw new InvalidOperationException($"Can not write {method.Name}. {action.Type} requires at least one parameter marked with [FromBody] or can have only one parameter"); } } if (action.Parameters.Count(x => x.FromBody) > 1) { throw new InvalidOperationException($"Can not write {method.Name}. {action.Type} can have only one parameter marked with [FromBody] or only one reference type"); } int tries = 0; while (controller.Actions.Any(a => a.Name == action.Name)) { if (tries > 10) { throw new InvalidOperationException($"Can not find a suitable name for {action.Name}"); } if (parameters.Count > 0 && tries == 0) { action.Name += "By" + parameters.First().Name.FirstCharToUpper(); } else if (parameters.Count > tries) { action.Name += "And" + parameters.Skip(tries).First().Name.FirstCharToUpper(); } else { action.Name += tries - parameters.Count + 1; } tries++; } controller.Actions.Add(action); } } transferObjects.Add(controller); }
public void Read(AspDotNetReadConfiguration configuration) { configuration.Hub.AssertIsNotNull($"SignalR: {nameof(configuration.Hub)}"); configuration.Hub.Name.AssertIsNotNull($"SignalR: {nameof(configuration.Hub)}.{nameof(configuration.Hub.Name)}"); configuration.Hub.Namespace.AssertIsNotNull($"SignalR: {nameof(configuration.Hub)}.{nameof(configuration.Hub.Namespace)}"); Logger.Trace($"Read SignalR hub {configuration.Hub.Namespace}.{configuration.Hub.Name}..."); Type type = GeneratorTypeLoader.Get(configuration.Hub.Assembly, configuration.Hub.Namespace, configuration.Hub.Name); if (type == null || type.BaseType == null || type.BaseType.Name != "Hub`1") { return; } if (!type.BaseType.IsGenericType) { Logger.Error("Implement generic Hub<T> instead of non-generic Hub type"); } SignalRHubTransferObject hub = new(); hub.Name = type.Name; hub.Language = ReflectionLanguage.Instance; IAspDotNetOptions typeOptions = this.aspOptions.Get(type); this.aspOptions.Set(hub, typeOptions); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); foreach (MethodInfo method in methods) { if (method.Name == "OnConnectedAsync" || method.Name == "OnDisconnectedAsync") { continue; } IOptions methodOptions = this.options.Get(method); HttpServiceActionTransferObject action = new(); action.Name = method.Name; if (method.ReturnType.Name != typeof(void).Name && method.ReturnType.Name != nameof(Task)) { Logger.Error($"Return type of method {method.Name} in {hub.Name} has to be void or Task"); } foreach (ParameterInfo parameter in method.GetParameters()) { action.Parameters.Add(new HttpServiceActionParameterTransferObject { Name = parameter.Name, Type = this.modelReader.Read(parameter.ParameterType, methodOptions) }); } hub.Actions.Add(action); } Type notificationType = type.BaseType.GetGenericArguments().Single(); MethodInfo[] notificationMethods = notificationType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); foreach (MethodInfo method in notificationMethods) { IOptions methodOptions = this.options.Get(method); HttpServiceActionTransferObject action = new(); action.Name = method.Name; foreach (ParameterInfo parameter in method.GetParameters()) { action.Parameters.Add(new HttpServiceActionParameterTransferObject { Name = parameter.Name, Type = this.modelReader.Read(parameter.ParameterType, methodOptions) }); } hub.Events.Add(action); } transferObjects.Add(hub); }
public virtual void Read(AspDotNetReadConfiguration configuration, List <ITransferObject> transferObjects) { configuration.Controller.AssertIsNotNull($"ASP: {nameof(configuration.Controller)}"); configuration.Controller.Name.AssertIsNotNull($"ASP: {nameof(configuration.Controller)}.{nameof(configuration.Controller.Name)}"); configuration.Controller.Namespace.AssertIsNotNull($"ASP: {nameof(configuration.Controller)}.{nameof(configuration.Controller.Namespace)}"); Logger.Trace($"Read ASP.NET controller {configuration.Controller.Namespace}{configuration.Controller.Name}..."); Type type = GeneratorTypeLoader.Get(configuration, configuration.Controller.Assembly, configuration.Controller.Namespace, configuration.Controller.Name); if (type == null) { return; } HttpServiceTransferObject controller = new HttpServiceTransferObject(); controller.Name = type.Name; controller.Language = ReflectionLanguage.Instance; Attribute routeAttribute = type.GetCustomAttributes().FirstOrDefault(); controller.Route = routeAttribute?.GetType().GetProperty("Template")?.GetValue(routeAttribute)?.ToString(); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); foreach (MethodInfo method in methods) { this.modelReader.Read(method.ReturnType, transferObjects); foreach (Attribute attribute in method.GetCustomAttributes()) { Type attributeType = attribute.GetType(); HttpServiceActionTransferObject action = new HttpServiceActionTransferObject(); action.ReturnType = method.ReturnType.ToTransferObject(); if (action.ReturnType.Name == "ActionResult") { action.ReturnType = action.ReturnType.Generics.Single().Type; } action.Route = attributeType.GetProperty("Template")?.GetValue(attribute)?.ToString(); int methodNameIndex = 1; while (true) { string actionName = $"{method.Name}{(methodNameIndex > 1 ? methodNameIndex.ToString() : "")}"; if (controller.Actions.All(x => !x.Name.Equals(actionName))) { action.Name = actionName; break; } methodNameIndex++; } ParameterInfo[] parameters = method.GetParameters(); foreach (ParameterInfo parameter in parameters) { this.modelReader.Read(parameter.ParameterType, transferObjects); } switch (attributeType.Name) { case "HttpGetAttribute": action.Type = HttpServiceActionTypeTransferObject.Get; break; case "HttpPostAttribute": action.Type = HttpServiceActionTypeTransferObject.Post; break; case "HttpPatchAttribute": action.Type = HttpServiceActionTypeTransferObject.Patch; break; case "HttpPutAttribute": action.Type = HttpServiceActionTypeTransferObject.Put; break; case "HttpDeleteAttribute": action.Type = HttpServiceActionTypeTransferObject.Delete; break; case "ConditionalAttribute": // Ignore these attributes continue; default: Logger.Warning($"Unknown controller action attribute {attributeType.Name}"); continue; } action.RequireBodyParameter = action.Type.IsBodyParameterRequired(); foreach (ParameterInfo parameter in parameters) { HttpServiceActionParameterTransferObject actionParameter = new HttpServiceActionParameterTransferObject(); actionParameter.Name = parameter.Name; actionParameter.Type = parameter.ParameterType.ToTransferObject(); actionParameter.FromBody = action.RequireBodyParameter && parameter.GetCustomAttributes().Any(parameterAttribute => parameterAttribute.GetType().Name == "FromBodyAttribute"); actionParameter.Inline = action.Route != null && action.Route.Contains($"{{{parameter.Name}}}"); actionParameter.InlineIndex = actionParameter.Inline ? action.Route.IndexOf($"{{{parameter.Name}}}", StringComparison.Ordinal) : 0; action.Parameters.Add(actionParameter); } if (action.RequireBodyParameter) { if (action.Parameters.Count == 0) { throw new InvalidOperationException($"Can not write {method.Name}. {action.Type} requires at least one parameter, but no parameter found."); } if (action.Parameters.Count == 1) { action.Parameters.Single().FromBody = true; } else if (action.Parameters.All(x => !x.FromBody)) { throw new InvalidOperationException($"Can not write {method.Name}. {action.Type} requires at least one parameter marked with [FromBody] or can have only one parameter"); } } controller.Actions.Add(action); } } transferObjects.Add(controller); }