Добавлен кодген для прокси для свойств и индексаторов

This commit is contained in:
2025-03-08 12:10:12 +03:00
parent 593a8b0635
commit 6aa11ba7c0
2 changed files with 73 additions and 24 deletions
+15 -1
View File
@@ -1,11 +1,21 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Example.Shared; using Example.Shared;
using mROA.Abstract;
using mROA.Implementation;
namespace Example.Backend namespace Example.Backend
{ {
public class PagesList : IPagesList public class PagesList : RemoteObjectBase, IPagesList
{ {
public IReadOnlyList<IPage> Collection { get; }
public Example.Shared.IPage this[int index]
{
get => GetResultAsync<Example.Shared.IPage>(3, new object[] { index }).GetAwaiter().GetResult();
set => CallAsync(5, new object[] { index, value }).Wait();
}
public IPage Get(int index) public IPage Get(int index)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
@@ -28,5 +38,9 @@ namespace Example.Backend
{ {
// TODO release managed resources here // TODO release managed resources here
} }
public PagesList(int id, IRepresentationModule representationModule) : base(id, representationModule)
{
}
} }
} }
+58 -23
View File
@@ -1,3 +1,5 @@
// #define DONT_ADD
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
@@ -41,11 +43,13 @@ namespace mROA.Codegen
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
var className = classDeclarationSyntax.Identifier.Text; var className = classDeclarationSyntax.Identifier.Text;
innerMethods = CollectMembers(classSymbol) innerMethods = CollectMembers(classSymbol);
.Where(i => i.MethodKind != MethodKind.EventAdd || i.MethodKind != MethodKind.EventRemove) var associated = innerMethods.Select(i => i.AssociatedSymbol).Where(i => i != null)
.Distinct(SymbolEqualityComparer.Default).Cast<ISymbol>().ToList();
innerMethods = innerMethods.Where(i =>
i.MethodKind != MethodKind.EventAdd && i.MethodKind != MethodKind.EventRemove)
.ToList(); .ToList();
var associated = innerMethods.Select(i => i.AssociatedSymbol as IPropertySymbol).Where(i => i != null)
.Select(i => i!).Distinct(SymbolEqualityComparer.Default).Cast<IPropertySymbol>().ToList();
var originalName = className; var originalName = className;
@@ -68,9 +72,35 @@ namespace mROA.Codegen
} }
} }
foreach (var prop in associated) foreach (var symbol in associated)
{ {
var start = $"public {prop.Type.ToDisplayString()} {prop.Name}"; switch (symbol)
{
case IPropertySymbol propertySymbol:
var setter = propertiesAccessMethods.FirstOrDefault(i =>
i.Item2.AssociatedSymbol!.Name == propertySymbol.Name && i.Item2.ReturnsVoid);
var getter = propertiesAccessMethods.FirstOrDefault(i =>
i.Item2.AssociatedSymbol!.Name == propertySymbol.Name && !i.Item2.ReturnsVoid);
string impl;
if (propertySymbol.IsIndexer)
{
impl =
$"public {propertySymbol.Type.ToDisplayString()} this[{string.Join(", ", propertySymbol.Parameters.Select(p => p.ToDisplayString()))}] {{ {getter.Item1} {setter.Item1} }}";
}
else
{
impl =
$"public {propertySymbol.Type.ToDisplayString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}";
}
declaredMethods.Add(impl);
break;
case IEventSymbol eventSymbol:
declaredMethods.Add(
$"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
break;
}
} }
var code = $@"// <auto-generated/> var code = $@"// <auto-generated/>
@@ -89,15 +119,16 @@ namespace {namespaceName}
{{ {{
}} }}
{string.Join("\r\n\t", declaredMethods)} {string.Join("\r\n\t\t", declaredMethods)}
}} }}
}} }}
"; ";
// Add the source code to the compilation. // Add the source code to the compilation.
// context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8)); #if !DONT_ADD
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
#endif
frontendContextRepo.Add( frontendContextRepo.Add(
$"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}"); $"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}");
} }
@@ -161,7 +192,9 @@ namespace mROA.Codegen
}} }}
}} }}
"; ";
// context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8)); #if !DONT_ADD
context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8));
#endif
} }
} }
@@ -184,12 +217,13 @@ namespace mROA.Codegen
isAsync = namedType.Name == "Task"; isAsync = namedType.Name == "Task";
isVoid = isAsync && namedType.TypeParameters.Length == 0 || namedType.Name == "Void"; isVoid = isAsync && namedType.TypeParameters.Length == 0 || namedType.Name == "Void";
parameters = method.Parameters.ToList(); parameters = method.Parameters.ToList();
parameters.RemoveAll(i => i.Type.Name is "CancellationToken" or "RequestContext"); parameters.RemoveAll(ParameterFilter);
isParametrized = parameters.Count != 0; isParametrized = parameters.Count != 0;
break; break;
case IArrayTypeSymbol: case IArrayTypeSymbol:
isAsync = false; isAsync = false;
isVoid = false; isVoid = false;
parameters = new List<IParameterSymbol>();
isParametrized = method.Parameters.Length != 0; isParametrized = method.Parameters.Length != 0;
break; break;
default: default:
@@ -206,12 +240,11 @@ namespace mROA.Codegen
var prefix = isAsync ? "await " : ""; var prefix = isAsync ? "await " : "";
var postfix = !isAsync ? isVoid ? ".Wait()" : ".GetAwaiter().GetResult()" : ""; var postfix = !isAsync ? isVoid ? ".Wait()" : ".GetAwaiter().GetResult()" : "";
var parameterLink = isParametrized var parameterLink = isParametrized
? ", new object[] {" + string.Join(", ", method.Parameters.Select(i => i.Name)) + "}" ? ", new object[] {" + string.Join(", ", parameters.Select(i => i.Name)) + "}"
: string.Empty; : string.Empty;
var tokenInsert = isAsync var tokenInsert = isAsync && method.Parameters.FirstOrDefault(i => i.Type.Name == "CancellationToken") is
? isParametrized { } tokenSymbol
? ", cancellationToken : " + method.Parameters[1].Name ? ", cancellationToken : " + tokenSymbol.Name
: ", cancellationToken : " + method.Parameters[0].Name
: String.Empty; : String.Empty;
var caller = isVoid var caller = isVoid
? $"CallAsync({index}{parameterLink}{tokenInsert})" ? $"CallAsync({index}{parameterLink}{tokenInsert})"
@@ -229,11 +262,14 @@ namespace mROA.Codegen
declaretedMethods.Add(sb.ToString()); declaretedMethods.Add(sb.ToString());
} }
private static Predicate<IParameterSymbol> ParameterFilter =
i => i.Type.Name is "CancellationToken" or "RequestContext";
public void GeneratePropertyMethod(IMethodSymbol method, List<IMethodSymbol> methods, public void GeneratePropertyMethod(IMethodSymbol method, List<IMethodSymbol> methods,
List<(string, IMethodSymbol)> propsCollection) List<(string, IMethodSymbol)> propsCollection)
{ {
var index = methods.IndexOf(method); var index = methods.IndexOf(method);
var sb = new StringBuilder(); var sb = "";
if (method.MethodKind == MethodKind.PropertyGet) if (method.MethodKind == MethodKind.PropertyGet)
{ {
var parametersArray = ""; var parametersArray = "";
@@ -242,19 +278,18 @@ namespace mROA.Codegen
parametersArray = $", new object[] {{{string.Join(", ", method.Parameters.Select(p => p.Name))}}}"; parametersArray = $", new object[] {{{string.Join(", ", method.Parameters.Select(p => p.Name))}}}";
} }
sb.AppendLine( sb =
$"get => GetResultAsync<{method.ReturnType.ToDisplayString()}>({index}{parametersArray}).Wait();"); $"get => GetResultAsync<{method.ReturnType.ToDisplayString()}>({index}{parametersArray}).GetAwaiter().GetResult();";
} }
else else
{ {
var parametersArray = ""; var parametersArray = "value";
if (method.Parameters.Length != 0) if (method.Parameters.Length != 0)
{ {
parametersArray = ", " + string.Join(", ", method.Parameters.Select(p => p.Name)); parametersArray = string.Join(", ", method.Parameters.Select(p => p.Name));
} }
sb.AppendLine( sb = $"set => CallAsync({index}, new object[] {{ {parametersArray} }}).Wait();";
$"set => CallAsync({index}, new object[] {{ value{parametersArray} }}).GetAwaiter().GetResult();");
} }
propsCollection.Add((sb.ToString(), method)); propsCollection.Add((sb.ToString(), method));