Переписывание евент-биндеров

This commit is contained in:
2025-03-26 14:43:06 +03:00
parent 5d5c3d1e2b
commit c4d9a54942
5 changed files with 69 additions and 63 deletions
+34 -4
View File
@@ -12,11 +12,41 @@ namespace mROA.Codegen
{ {
static RemoteTypeBinder(){ static RemoteTypeBinder(){
RemoteContextRepository.RemoteTypes = new Dictionary<Type, Type> { RemoteContextRepository.RemoteTypes = new Dictionary<Type, Type> {
<!I remoteTypePair r sep typesSep><!D typesSep>, <!I remoteTypePair r sep typesSep><!D typesSep>,
<!D>}; <!D>
};
ContextRepository.EventBinders = new object[] { ContextRepository.EventBinders = new object[] {
<!I eventBinder r sep typesSep> <!I eventBinder r sep typesSep>
}; <!T objectBinderTemplate>
new EventBinder<<!L type>>
{
BindAction = (instance, context, representationProducer, index) =>
{
var ownerId = context.OwnerId;
var module = representationProducer.Produce(ownerId);
<!I eventBinder r sep typesSep><!D typesSep>
<!D>
<!T eventBinderTemplate>
(instance as <!L type>).<!L eventName> += (<!L parametersDeclaration>) =>
{
Console.WriteLine($"Try to send to {ownerId} with hash code {context.GetHashCode()}");
<!I callFilter>
Console.WriteLine("Sending event...");
var request = new DefaultCallRequest
{
CommandId = <!L commandId>,
ObjectId = new ComplexObjectIdentifier(index, ownerId),
Parameters = new object[] { <!L transferParameters> }
};
module.PostCallMessageAsync(request.Id, MessageType.EventRequest, request);
};
<!T>
}
}
<!T>
};
} }
} }
} }
@@ -4,7 +4,7 @@ using System.Linq;
namespace mROA.CodegenTools namespace mROA.CodegenTools
{ {
public class InsertTemplatePart : ITagged, IBaking public class InsertTemplateSection : ITagged, IBaking
{ {
private object _insertedValue; private object _insertedValue;
private string _tag; private string _tag;
@@ -12,7 +12,7 @@ namespace mROA.CodegenTools
public TemplateDocument Context { get; set; } public TemplateDocument Context { get; set; }
public readonly List<string> Parameters; public readonly List<string> Parameters;
public InsertTemplatePart(string tag, TemplateDocument context, params string[] parameters) public InsertTemplateSection(string tag, TemplateDocument context, params string[] parameters)
{ {
_tag = tag; _tag = tag;
Parameters = parameters.ToList(); Parameters = parameters.ToList();
@@ -31,7 +31,7 @@ namespace mROA.CodegenTools
private void ProduceInserted(object value) private void ProduceInserted(object value)
{ {
var currentIndex = Context.Parts.IndexOf(this); var currentIndex = Context.Parts.IndexOf(this);
var clone = (InsertTemplatePart)MemberwiseClone(); var clone = (InsertTemplateSection)MemberwiseClone();
clone._tag += "+"; clone._tag += "+";
clone._insertedValue = value; clone._insertedValue = value;
@@ -80,7 +80,7 @@ namespace mROA.CodegenTools
public object Clone() public object Clone()
{ {
return new InsertTemplatePart(_tag, Context, Parameters.ToArray()); return new InsertTemplateSection(_tag, Context, Parameters.ToArray());
} }
} }
} }
@@ -18,7 +18,7 @@ namespace mROA.CodegenTools
var tagText = GetTagValue(from, to); var tagText = GetTagValue(from, to);
var parts = tagText.Split(' '); var parts = tagText.Split(' ');
return new InsertTemplatePart(parts[0], document, parts.Skip(1).ToArray()); return new InsertTemplateSection(parts[0], document, parts.Skip(1).ToArray());
} }
} }
} }
+1 -1
View File
@@ -14,7 +14,7 @@ namespace mROA.CodegenTools
public void Insert(string tag, object value) public void Insert(string tag, object value)
{ {
var selectedPart = this[tag]; var selectedPart = this[tag];
if (selectedPart is InsertTemplatePart itp) if (selectedPart is InsertTemplateSection itp)
{ {
itp.Setup(value); itp.Setup(value);
} }
+25 -49
View File
@@ -80,12 +80,7 @@ namespace mROA.Codegen
private void GenerateCode(GeneratorExecutionContext context, Compilation compilation, private void GenerateCode(GeneratorExecutionContext context, Compilation compilation,
ImmutableArray<InterfaceDeclarationSyntax> classes) ImmutableArray<InterfaceDeclarationSyntax> classes)
{ {
// For future
// var asm = Assembly.GetAssembly(typeof(mROASourceGenerator));
// var files = asm.GetManifestResourceNames();
// var test = asm.GetManifestResourceStream("mROA.Codegen.test.tpt");
// var reader = new StreamReader(test);
// var allText = reader.ReadToEnd();
List<IMethodSymbol> totalMethods = new List<IMethodSymbol>(); List<IMethodSymbol> totalMethods = new List<IMethodSymbol>();
@@ -155,11 +150,13 @@ namespace mROA.Codegen
impl = impl =
$"public {propertySymbol.Type.ToDisplayString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}"; $"public {propertySymbol.Type.ToDisplayString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}";
} }
ClassTemplate.Insert("methods", impl); ClassTemplate.Insert("methods", impl);
// declaredMethods.Add(impl); // declaredMethods.Add(impl);
break; break;
case IEventSymbol eventSymbol: case IEventSymbol eventSymbol:
ClassTemplate.Insert("methods", $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};"); ClassTemplate.Insert("methods",
$"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
// declaredMethods.Add( // declaredMethods.Add(
// $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};"); // $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
break; break;
@@ -206,7 +203,8 @@ namespace mROA.Codegen
} }
} }
private void GenerateEventImplementation(INamedTypeSymbol classSymbol, List<string> invokers, GeneratorExecutionContext context) private void GenerateEventImplementation(INamedTypeSymbol classSymbol, List<string> invokers,
GeneratorExecutionContext context)
{ {
var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers()) var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers())
.OfType<IEventSymbol>().ToList(); .OfType<IEventSymbol>().ToList();
@@ -217,6 +215,7 @@ namespace mROA.Codegen
InterfaceTemplate.AddDefine("name", classSymbol.Name); InterfaceTemplate.AddDefine("name", classSymbol.Name);
InterfaceTemplate.AddDefine("namespace", classSymbol.ContainingNamespace.ToDisplayString()); InterfaceTemplate.AddDefine("namespace", classSymbol.ContainingNamespace.ToDisplayString());
var singleEventBinder = new List<string>(events.Count); var singleEventBinder = new List<string>(events.Count);
var objectBinderTemplate = (TemplateDocument)((InnerTemplateSection)BinderTemplate["objectBinderTemplate"]).InnerTemplate.Clone();
for (int i = 0; i < events.Count; i++) for (int i = 0; i < events.Count; i++)
{ {
var currentEvent = events[i]; var currentEvent = events[i];
@@ -227,19 +226,11 @@ namespace mROA.Codegen
// declaredMethods.Add(additionalMethod); // declaredMethods.Add(additionalMethod);
InterfaceTemplate.Insert("signature", signature); InterfaceTemplate.Insert("signature", signature);
GenerateEventCode(currentEvent, invokers, classSymbol); GenerateEventCode(currentEvent, invokers, classSymbol);
GenerateBinderCode(currentEvent, invokers, classSymbol, singleEventBinder); GenerateBinderCode(currentEvent, invokers, classSymbol, objectBinderTemplate);
} }
objectBinderTemplate.AddDefine("type", classSymbol.ToDisplayString());
var partialInterface = InterfaceTemplate.Compile(); var partialInterface = InterfaceTemplate.Compile();
var binder = $@"new EventBinder<{classSymbol.ToDisplayString()}> var binder = objectBinderTemplate.Compile();
{{
BindAction = (instance, context, representationProducer, index) =>
{{
var ownerId = context.OwnerId;
var module = representationProducer.Produce(ownerId);
{string.Join("\r\n", singleEventBinder)}
}}
}}";
BinderTemplate.Insert("eventBinder", binder); BinderTemplate.Insert("eventBinder", binder);
#if !DONT_ADD #if !DONT_ADD
@@ -409,10 +400,12 @@ namespace mROA.Codegen
} }
private void GenerateBinderCode(IEventSymbol eventSymbol, List<string> invokers, INamedTypeSymbol baseType, private void GenerateBinderCode(IEventSymbol eventSymbol, List<string> invokers, INamedTypeSymbol baseType,
List<string> binders) TemplateDocument document)
{ {
var eventBinderTemplate = (TemplateDocument)((InnerTemplateSection)document["eventBinderTemplate"]!).InnerTemplate.Clone();
var index = invokers.Count - 1; var index = invokers.Count - 1;
var parameters = (eventSymbol.Type as INamedTypeSymbol).TypeArguments.ToList(); var parameters = (eventSymbol.Type as INamedTypeSymbol)!.TypeArguments.ToList();
int parameterIndex = 0; int parameterIndex = 0;
var parametersDeclaration = string.Join(", ", var parametersDeclaration = string.Join(", ",
JoinWithComa(Enumerable.Range(0, parameters.Count).Select(i => "p" + i++))); JoinWithComa(Enumerable.Range(0, parameters.Count).Select(i => "p" + i++)));
@@ -421,28 +414,23 @@ namespace mROA.Codegen
JoinWithComa(parameters.Where(i => !ParameterFilterForType(i)) JoinWithComa(parameters.Where(i => !ParameterFilterForType(i))
.Select(i => "p" + parameters.IndexOf(i))); .Select(i => "p" + parameters.IndexOf(i)));
var callFilter = ""; string callFilter;
var requestIndex = parameters.FindIndex(i => i.Name == "RequestContext"); var requestIndex = parameters.FindIndex(i => i.Name == "RequestContext");
if (requestIndex != -1) if (requestIndex != -1)
{ {
callFilter = $"\n\r\t\t\tif(ownerId == p{requestIndex}.OwnerId) return;"; callFilter = $"\n\r\t\t\tif(ownerId == p{requestIndex}.OwnerId) return;";
eventBinderTemplate.AddDefine("callFilter", callFilter);
} }
var eventBinderCode = eventBinderTemplate.AddDefine("type", baseType.ToDisplayString());
$@" (instance as {baseType.ToDisplayString()}).{eventSymbol.Name} += ({parametersDeclaration}) => eventBinderTemplate.AddDefine("eventName", eventSymbol.Name);
{{ eventBinderTemplate.AddDefine("parametersDeclaration", parametersDeclaration);
Console.WriteLine($""Try to send to {{ownerId}} with hash code {{context.GetHashCode()}}""); eventBinderTemplate.AddDefine("commandId", index.ToString());
{callFilter} eventBinderTemplate.AddDefine("transferParameters", transferParameters);
Console.WriteLine(""Sending event...""); var eventBinderCode = eventBinderTemplate.Compile();
var request = new DefaultCallRequest document.Insert("eventBinder", eventBinderCode);
{{
CommandId = {index}, ObjectId = new ComplexObjectIdentifier(index, ownerId), Parameters = new object[] {{ {transferParameters} }}
}};
module.PostCallMessageAsync(request.Id, MessageType.EventRequest, request);
}};
";
binders.Add(eventBinderCode);
} }
public static string JoinWithComa(IEnumerable<string> parts) => string.Join(", ", parts); public static string JoinWithComa(IEnumerable<string> parts) => string.Join(", ", parts);
@@ -545,20 +533,8 @@ namespace mROA.Codegen
var parameterTypes = string.Join(", ", var parameterTypes = string.Join(", ",
$"{string.Join(", ", method.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}"); $"{string.Join(", ", method.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}");
var parameterInserts = string.Join(", ", var parameterInserts = string.Join(", ",
method.Parameters.Take(method.Parameters.Length - 1).Select(p => method.Parameters.Take(method.Parameters.Length - 1).Select(p => Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
{
return Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]");
// if (!p.Type.IsValueType)
// return "parameters[" + method.Parameters.IndexOf(p) + "] as " +
// p.Type.ToDisplayString();
// return $"({p.Type.ToDisplayString()})parameters[{method.Parameters.IndexOf(p)}]";
}
));
// var valueInsert = !method.Parameters.Last().Type.IsValueType
// ? "parameters[" + (method.Parameters.Length - 1) + "] as " +
// method.Parameters.Last().Type.ToDisplayString()
// : $"({method.Parameters.Last().Type.ToDisplayString()})parameters[{method.Parameters.Length - 1}]";
var valueInsert = Caster(method.Parameters.Last().Type, var valueInsert = Caster(method.Parameters.Last().Type,
"parameters[" + (method.Parameters.Length - 1) + "]"); "parameters[" + (method.Parameters.Length - 1) + "]");
backend = $@"new mROA.Implementation.MethodInvoker backend = $@"new mROA.Implementation.MethodInvoker