diff --git a/InterfaceStubGenerator/GeneratedInterfaceStubTemplate.mustache b/InterfaceStubGenerator/GeneratedInterfaceStubTemplate.mustache index 88f23c662..449d8a836 100644 --- a/InterfaceStubGenerator/GeneratedInterfaceStubTemplate.mustache +++ b/InterfaceStubGenerator/GeneratedInterfaceStubTemplate.mustache @@ -61,6 +61,24 @@ namespace {{Namespace}} } {{/MethodList}} + +{{#PropertyList}} + public {{Type}} {{Name}} + { +{{#IsRefitProperty}} + get + { + var attribute = GetType().GetInterfaceMap(typeof({{InterfaceName}}{{#TypeParameters}}<{{.}}>{{/TypeParameters}})).InterfaceType + .GetProperty("{{Name}}").GetCustomAttributes(typeof(Refit.ComposeAttribute), false) + .OfType().FirstOrDefault(); + return Refit.RestService.For<{{Type}}>(new Uri(Client.BaseAddress, attribute.Uri).AbsoluteUri); + } +{{/IsRefitProperty}} +{{^IsRefitProperty}} + get { throw new NotImplementedException("This property has no Refit composition attribute."); } +{{/IsRefitProperty}} + } +{{/PropertyList}} } } diff --git a/InterfaceStubGenerator/InterfaceStubGenerator.cs b/InterfaceStubGenerator/InterfaceStubGenerator.cs index 935289602..0366b5180 100644 --- a/InterfaceStubGenerator/InterfaceStubGenerator.cs +++ b/InterfaceStubGenerator/InterfaceStubGenerator.cs @@ -51,7 +51,8 @@ public List FindInterfacesToGenerate(SyntaxTree tree return new List(); return nodes.OfType() - .Where(i => i.Members.OfType().Any(HasRefitHttpMethodAttribute)) + .Where(i => i.Members.OfType().Any(HasRefitHttpMethodAttribute) || + i.Members.OfType().Any(HasInterfaceCompositionAttribute)) .ToList(); } @@ -70,6 +71,16 @@ public bool HasRefitHttpMethodAttribute(MethodDeclarationSyntax method) a.ArgumentList.Arguments[0].Expression.CSharpKind() == SyntaxKind.StringLiteralExpression); } + static readonly HashSet interfaceCompositionAttributeNames = new HashSet( + new[] {"Compose"} + .SelectMany(x => new[] {"{0}", "{0}Attribute"}.Select(f => string.Format(f, x)))); + + public bool HasInterfaceCompositionAttribute(PropertyDeclarationSyntax property) + { + return property.AttributeLists.SelectMany(a => a.Attributes) + .Any(a => interfaceCompositionAttributeNames.Contains(a.Name.ToString().Split('.').Last())); + } + public TemplateInformation GenerateTemplateInfoForInterfaceList(List interfaceList) { var usings = interfaceList @@ -123,6 +134,15 @@ public ClassTemplateInfo GenerateClassInfoForInterface(InterfaceDeclarationSynta }) .ToList(); + ret.PropertyList = interfaceTree.Members + .OfType() + .Select(x => new PropertyTemplateInfo() { + Name = x.Identifier.ValueText, + Type = x.Type.ToString(), + IsRefitProperty = HasInterfaceCompositionAttribute(x) + }) + .ToList(); + return ret; } @@ -156,6 +176,7 @@ public class ClassTemplateInfo public string TypeParameters { get; set; } public string ConstraintClauses { get; set; } public List MethodList { get; set; } + public List PropertyList { get; set; } } public class MethodTemplateInfo @@ -167,6 +188,13 @@ public class MethodTemplateInfo public bool IsRefitMethod { get; set; } } + public class PropertyTemplateInfo + { + public string Type { get; set; } + public string Name { get; set; } + public bool IsRefitProperty { get; set; } + } + public class TemplateInformation { public List UsingList { get; set; } diff --git a/Refit/Attributes.cs b/Refit/Attributes.cs index 1d8539afb..210e8855b 100644 --- a/Refit/Attributes.cs +++ b/Refit/Attributes.cs @@ -115,4 +115,15 @@ public HeaderAttribute(string header) Header = header; } } + + [AttributeUsage(AttributeTargets.Property)] + public class ComposeAttribute : Attribute + { + public string Uri { get; private set; } + + public ComposeAttribute(string uri) + { + Uri = uri; + } + } }