diff --git a/Esiur/Data/RepresentationType.cs b/Esiur/Data/RepresentationType.cs index 54bf778..0c29830 100644 --- a/Esiur/Data/RepresentationType.cs +++ b/Esiur/Data/RepresentationType.cs @@ -168,6 +168,12 @@ namespace Esiur.Data public RepresentationType?[] SubTypes = new RepresentationType[3]; + + public RepresentationType ToNullable() + { + return new RepresentationType(Identifier, true, GUID, SubTypes); + } + public static RepresentationType? FromType(Type type) { diff --git a/Esiur/Net/IIP/DistributedConnectionProtocol.cs b/Esiur/Net/IIP/DistributedConnectionProtocol.cs index a4b2df4..ab64d57 100644 --- a/Esiur/Net/IIP/DistributedConnectionProtocol.cs +++ b/Esiur/Net/IIP/DistributedConnectionProtocol.cs @@ -46,6 +46,8 @@ partial class DistributedConnection KeyList> resourceRequests = new KeyList>(); KeyList> templateRequests = new KeyList>(); + KeyList> templateByNameRequests = new KeyList>(); + KeyList> pathRequests = new KeyList>(); @@ -1888,6 +1890,39 @@ partial class DistributedConnection return reply; } + + public AsyncReply GetTemplateByClassName(string className) + { + var template = templates.Values.FirstOrDefault(x => x.ClassName == className); + if (template != null) + return new AsyncReply(template); + + if (templateByNameRequests.ContainsKey(className)) + return templateByNameRequests[className]; + + var reply = new AsyncReply(); + templateByNameRequests.Add(className, reply); + + var classNameBytes = DC.ToBytes(className); + + SendRequest(IIPPacket.IIPPacketAction.TemplateFromClassName) + .AddUInt8((byte)classNameBytes.Length) + .AddUInt8Array(classNameBytes) + .Done() + .Then((rt) => + { + templateByNameRequests.Remove(className); + templates.Add(((TypeTemplate)rt[0]).ClassId, (TypeTemplate)rt[0]); + Warehouse.PutTemplate(rt[0] as TypeTemplate); + reply.Trigger(rt[0]); + }).Error((ex) => + { + reply.TriggerError(ex); + }); + + return reply; + } + // IStore interface /// /// Get a resource by its path. diff --git a/Esiur/Net/IIP/DistributedResource.cs b/Esiur/Net/IIP/DistributedResource.cs index 9d129b4..219dda6 100644 --- a/Esiur/Net/IIP/DistributedResource.cs +++ b/Esiur/Net/IIP/DistributedResource.cs @@ -222,6 +222,7 @@ public class DistributedResource : DynamicObject, IResource public AsyncReply _Invoke(byte index, Map args) { + if (destroyed) throw new Exception("Trying to access destroyed object"); diff --git a/Esiur/Proxy/TemplateGenerator.cs b/Esiur/Proxy/TemplateGenerator.cs index 888de20..9bcf40e 100644 --- a/Esiur/Proxy/TemplateGenerator.cs +++ b/Esiur/Proxy/TemplateGenerator.cs @@ -284,12 +284,42 @@ public static class TemplateGenerator continue; var rtTypeName = GetTypeName(f.ReturnType, templates); + + var positionalArgs = f.Arguments.Where((x) => !x.Optional).ToArray(); + var optionalArgs = f.Arguments.Where((x) => x.Optional).ToArray(); + + rt.Append($"public AsyncReply<{rtTypeName}> {f.Name}("); - rt.Append(string.Join(",", f.Arguments.Select(x => GetTypeName(x.Type, templates) + " " + x.Name))); + + + if (positionalArgs.Length > 0) + rt.Append( + String.Join(", ", positionalArgs.Select((a) => GetTypeName(a.Type, templates) + " " + a.Name))); + + if (optionalArgs.Length > 0) + { + if (positionalArgs.Length > 0) rt.Append(","); + + rt.Append( + String.Join(", ", optionalArgs.Select((a) => GetTypeName(a.Type.ToNullable(), templates) + " " + a.Name + " = null"))); + } + + //rt.Append(string.Join(",", f.Arguments.Select(x => GetTypeName(x.Type, templates) + " " + x.Name))); rt.AppendLine(") {"); + + rt.AppendLine( + $"var args = new Map(){{{ String.Join(", ", positionalArgs.Select((e) => "[" + e.Index + "] = " + e.Name))}}};"); + + foreach(var a in optionalArgs) { + rt.AppendLine( + $"if ({a.Name} != null) args[{a.Index}] = {a.Name};"); + } + + rt.AppendLine($"var rt = new AsyncReply<{rtTypeName}>();"); - rt.AppendLine($"_InvokeByArrayArguments({f.Index}, new object[] {{ { string.Join(", ", f.Arguments.Select(x => x.Name)) } }})"); + //rt.AppendLine($"_Invoke({f.Index}, new Map[] {{ { string.Join(", ", f.Arguments.Select(x => x.Name)) } }})"); + rt.AppendLine($"_Invoke({f.Index}, args)"); rt.AppendLine($".Then(x => rt.Trigger(({rtTypeName})x))"); rt.AppendLine($".Error(x => rt.TriggerError(x))"); rt.AppendLine($".Chunk(x => rt.TriggerChunk(x));"); diff --git a/Esiur/Resource/ResourceEvent.cs b/Esiur/Resource/ResourceEvent.cs index e2ff664..50b51e0 100644 --- a/Esiur/Resource/ResourceEvent.cs +++ b/Esiur/Resource/ResourceEvent.cs @@ -33,19 +33,19 @@ namespace Esiur.Resource; public class ResourceEvent : System.Attribute { - string expansion; + string annotation; - public string Expansion + public readonly string Annotation { get { - return expansion; + return annotation; } } - public ResourceEvent(string expansion = null) + public ResourceEvent(string annotation = null) { - this.expansion = expansion; + this.annotation = annotation; } } diff --git a/Esiur/Resource/ResourceFunction.cs b/Esiur/Resource/ResourceFunction.cs index 7a345db..211f5d5 100644 --- a/Esiur/Resource/ResourceFunction.cs +++ b/Esiur/Resource/ResourceFunction.cs @@ -33,19 +33,19 @@ namespace Esiur.Resource; [AttributeUsage(AttributeTargets.Method)] public class ResourceFunction : System.Attribute { - private string expansion = null; + private string annotation = null; - public string Expansion + public string Annotation { get { - return expansion; + return annotation; } } - public ResourceFunction(string expansion = null) + public ResourceFunction(string annotation = null) { - this.expansion = expansion; + this.annotation = annotation; } } diff --git a/Esiur/Resource/ResourceProperty.cs b/Esiur/Resource/ResourceProperty.cs index 4aec31f..c21eead 100644 --- a/Esiur/Resource/ResourceProperty.cs +++ b/Esiur/Resource/ResourceProperty.cs @@ -39,15 +39,15 @@ public class ResourceProperty : System.Attribute public readonly bool Nullable; public readonly StorageMode Storage; public readonly bool Serialize; - public readonly string ReadExpansion; - public readonly string WriteExpansion; + public readonly string ReadAnnotation; + public readonly string WriteAnnotation; public ResourceProperty(StorageMode storage = StorageMode.NonVolatile, bool serialize = true, - string readExpansion = null, string writeExpansion = null) + string readAnnotation = null, string writeAnnotation = null) { - this.ReadExpansion = readExpansion; - this.WriteExpansion = writeExpansion; + this.ReadAnnotation = readAnnotation; + this.WriteAnnotation = writeAnnotation; this.Storage = storage; this.Serialize = serialize; } diff --git a/Esiur/Resource/Template/ConstantTemplate.cs b/Esiur/Resource/Template/ConstantTemplate.cs index e8841df..a6690b5 100644 --- a/Esiur/Resource/Template/ConstantTemplate.cs +++ b/Esiur/Resource/Template/ConstantTemplate.cs @@ -9,13 +9,13 @@ public class ConstantTemplate : MemberTemplate { public readonly object Value; //public readonly byte[] ValueData; - public readonly string Expansion; + public readonly string Annotation; public readonly RepresentationType ValueType; - public ConstantTemplate(TypeTemplate template, byte index, string name, bool inherited, RepresentationType valueType, object value, string expansion) + public ConstantTemplate(TypeTemplate template, byte index, string name, bool inherited, RepresentationType valueType, object value, string annotation) : base(template, index, name, inherited) { - Expansion = expansion; + Annotation = annotation; ValueType = valueType; Value = value; //try @@ -36,9 +36,9 @@ public class ConstantTemplate : MemberTemplate var hdr = Inherited ? (byte)0x80 : (byte)0; - if (Expansion != null) + if (Annotation != null) { - var exp = DC.ToBytes(Expansion); + var exp = DC.ToBytes(Annotation); hdr |= 0x70; return new BinaryList() .AddUInt8(hdr) diff --git a/Esiur/Resource/Template/EventTemplate.cs b/Esiur/Resource/Template/EventTemplate.cs index d3da606..cf8a6dd 100644 --- a/Esiur/Resource/Template/EventTemplate.cs +++ b/Esiur/Resource/Template/EventTemplate.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace Esiur.Resource.Template; public class EventTemplate : MemberTemplate { - public string Expansion + public string Annotation { get; set; @@ -30,9 +30,9 @@ public class EventTemplate : MemberTemplate if (Listenable) hdr |= 0x8; - if (Expansion != null) + if (Annotation != null) { - var exp = DC.ToBytes(Expansion); + var exp = DC.ToBytes(Annotation); hdr |= 0x50; return new BinaryList() .AddUInt8(hdr) @@ -53,10 +53,10 @@ public class EventTemplate : MemberTemplate .ToArray(); } - public EventTemplate(TypeTemplate template, byte index, string name,bool inherited, RepresentationType argumentType, string expansion = null, bool listenable = false) + public EventTemplate(TypeTemplate template, byte index, string name,bool inherited, RepresentationType argumentType, string annotation = null, bool listenable = false) : base(template, index, name, inherited) { - this.Expansion = expansion; + this.Annotation = annotation; this.Listenable = listenable; this.ArgumentType = argumentType; } diff --git a/Esiur/Resource/Template/FunctionTemplate.cs b/Esiur/Resource/Template/FunctionTemplate.cs index 53ccf15..435f321 100644 --- a/Esiur/Resource/Template/FunctionTemplate.cs +++ b/Esiur/Resource/Template/FunctionTemplate.cs @@ -10,7 +10,7 @@ namespace Esiur.Resource.Template; public class FunctionTemplate : MemberTemplate { - public string Expansion + public string Annotation { get; set; @@ -39,7 +39,6 @@ public class FunctionTemplate : MemberTemplate var name = base.Compose(); var bl = new BinaryList() - //.AddUInt8(Expansion != null ? (byte)0x10 : (byte)0) .AddUInt8((byte)name.Length) .AddUInt8Array(name) .AddUInt8Array(ReturnType.Compose()) @@ -49,9 +48,9 @@ public class FunctionTemplate : MemberTemplate bl.AddUInt8Array(Arguments[i].Compose()); - if (Expansion != null) + if (Annotation != null) { - var exp = DC.ToBytes(Expansion); + var exp = DC.ToBytes(Annotation); bl.AddInt32(exp.Length) .AddUInt8Array(exp); bl.InsertUInt8(0, Inherited ? (byte)0x90 : (byte)0x10); @@ -62,12 +61,12 @@ public class FunctionTemplate : MemberTemplate return bl.ToArray(); } - public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, ArgumentTemplate[] arguments, RepresentationType returnType, string expansion = null) + public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, ArgumentTemplate[] arguments, RepresentationType returnType, string annotation = null) : base(template, index, name, inherited) { //this.IsVoid = isVoid; this.Arguments = arguments; this.ReturnType = returnType; - this.Expansion = expansion; + this.Annotation = annotation; } } diff --git a/Esiur/Resource/Template/PropertyTemplate.cs b/Esiur/Resource/Template/PropertyTemplate.cs index c4dcde2..a024eb9 100644 --- a/Esiur/Resource/Template/PropertyTemplate.cs +++ b/Esiur/Resource/Template/PropertyTemplate.cs @@ -55,13 +55,13 @@ public class PropertyTemplate : MemberTemplate set; }*/ - public string ReadExpansion + public string ReadAnnotation { get; set; } - public string WriteExpansion + public string WriteAnnotation { get; set; @@ -83,10 +83,10 @@ public class PropertyTemplate : MemberTemplate if (Inherited) pv |= 0x80; - if (WriteExpansion != null && ReadExpansion != null) + if (WriteAnnotation != null && ReadAnnotation != null) { - var rexp = DC.ToBytes(ReadExpansion); - var wexp = DC.ToBytes(WriteExpansion); + var rexp = DC.ToBytes(ReadAnnotation); + var wexp = DC.ToBytes(WriteAnnotation); return new BinaryList() .AddUInt8((byte)(0x38 | pv)) .AddUInt8((byte)name.Length) @@ -98,9 +98,9 @@ public class PropertyTemplate : MemberTemplate .AddUInt8Array(rexp) .ToArray(); } - else if (WriteExpansion != null) + else if (WriteAnnotation != null) { - var wexp = DC.ToBytes(WriteExpansion); + var wexp = DC.ToBytes(WriteAnnotation); return new BinaryList() .AddUInt8((byte)(0x30 | pv)) .AddUInt8((byte)name.Length) @@ -110,9 +110,9 @@ public class PropertyTemplate : MemberTemplate .AddUInt8Array(wexp) .ToArray(); } - else if (ReadExpansion != null) + else if (ReadAnnotation != null) { - var rexp = DC.ToBytes(ReadExpansion); + var rexp = DC.ToBytes(ReadAnnotation); return new BinaryList() .AddUInt8((byte)(0x28 | pv)) .AddUInt8((byte)name.Length) @@ -134,14 +134,14 @@ public class PropertyTemplate : MemberTemplate } public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited, - RepresentationType valueType, string read = null, string write = null, bool recordable = false) + RepresentationType valueType, string readAnnotation = null, string writeAnnotation = null, bool recordable = false) : base(template, index, name, inherited) { this.Recordable = recordable; //this.Storage = storage; - if (read != null) - this.ReadExpansion = read; - this.WriteExpansion = write; + if (readAnnotation != null) + this.ReadAnnotation = readAnnotation; + this.WriteAnnotation = writeAnnotation; this.ValueType = valueType; } } diff --git a/Esiur/Resource/Template/TypeTemplate.cs b/Esiur/Resource/Template/TypeTemplate.cs index 5c4c06f..8a14129 100644 --- a/Esiur/Resource/Template/TypeTemplate.cs +++ b/Esiur/Resource/Template/TypeTemplate.cs @@ -470,9 +470,9 @@ public class TypeTemplate pt.Recordable = storageAttr.Mode == StorageMode.Recordable; if (annotationAttr != null) - pt.ReadExpansion = annotationAttr.Annotation; + pt.ReadAnnotation = annotationAttr.Annotation; else - pt.ReadExpansion = GetTypeAnnotationName(pi.PropertyType); + pt.ReadAnnotation = GetTypeAnnotationName(pi.PropertyType); pt.PropertyInfo = pi; @@ -518,7 +518,7 @@ public class TypeTemplate et.EventInfo = ei; if (annotationAttr != null) - et.Expansion = annotationAttr.Annotation; + et.Annotation = annotationAttr.Annotation; if (listenableAttr != null) et.Listenable = true; @@ -627,9 +627,9 @@ public class TypeTemplate var ft = new FunctionTemplate(this, (byte)functions.Count, fn, mi.DeclaringType != type, arguments, rtType); if (annotationAttr != null) - ft.Expansion = annotationAttr.Annotation; + ft.Annotation = annotationAttr.Annotation; else - ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name; + ft.Annotation = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name; ft.MethodInfo = mi; functions.Add(ft); @@ -776,11 +776,11 @@ public class TypeTemplate var hasParent = HasParent(type); var classAnnotation = type.GetCustomAttribute(false); - var hasAnnotation = classAnnotation != null && classAnnotation.Annotation != null; + var hasClassAnnotation = classAnnotation != null && classAnnotation.Annotation != null; var classNameBytes = DC.ToBytes(className); - b.AddUInt8((byte)((hasParent ? 0x80 : 0) | (hasAnnotation ? 0x40 : 0x0) | (byte)templateType)) + b.AddUInt8((byte)((hasParent ? 0x80 : 0) | (hasClassAnnotation ? 0x40 : 0x0) | (byte)templateType)) .AddGuid(classId) .AddUInt8((byte)classNameBytes.Length) .AddUInt8Array(classNameBytes); @@ -793,7 +793,7 @@ public class TypeTemplate b.AddGuid(parentId); } - if (hasAnnotation) + if (hasClassAnnotation) { var classAnnotationBytes = DC.ToBytes(classAnnotation.Annotation); b.AddUInt16((ushort)classAnnotationBytes.Length) @@ -856,7 +856,7 @@ public class TypeTemplate od.content = data.Clip(offset, contentLength); var hasParent = (data[offset] & 0x80) > 0; - var hasAnnotation = (data[offset] & 0x40) > 0; + var hasClassAnnotation = (data[offset] & 0x40) > 0; od.templateType = (TemplateType)(data[offset++] & 0xF); @@ -872,7 +872,7 @@ public class TypeTemplate offset += 16; } - if (hasAnnotation) + if (hasClassAnnotation) { var len = data.GetUInt16(offset, Endian.Little); offset += 2; @@ -897,8 +897,8 @@ public class TypeTemplate if (type == 0) // function { - string expansion = null; - var hasExpansion = ((data[offset++] & 0x10) == 0x10); + string annotation = null; + var hasAnnotation = ((data[offset++] & 0x10) == 0x10); var name = data.GetString(offset + 1, data[offset]); offset += (uint)data[offset] + 1; @@ -919,25 +919,25 @@ public class TypeTemplate } // arguments - if (hasExpansion) // expansion ? + if (hasAnnotation) // Annotation ? { var cs = data.GetUInt32(offset, Endian.Little); offset += 4; - expansion = data.GetString(offset, cs); + annotation = data.GetString(offset, cs); offset += cs; } - var ft = new FunctionTemplate(od, functionIndex++, name, inherited, arguments.ToArray(), returnType, expansion); + var ft = new FunctionTemplate(od, functionIndex++, name, inherited, arguments.ToArray(), returnType, annotation); od.functions.Add(ft); } else if (type == 1) // property { - string readExpansion = null, writeExpansion = null; + string readAnnotation = null, writeAnnotation= null; - var hasReadExpansion = ((data[offset] & 0x8) == 0x8); - var hasWriteExpansion = ((data[offset] & 0x10) == 0x10); + var hasReadAnnotation = ((data[offset] & 0x8) == 0x8); + var hasWriteAnnotation = ((data[offset] & 0x10) == 0x10); var recordable = ((data[offset] & 1) == 1); var permission = (PropertyTemplate.PropertyPermission)((data[offset++] >> 1) & 0x3); var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]); @@ -948,31 +948,31 @@ public class TypeTemplate offset += dts; - if (hasReadExpansion) // expansion ? + if (hasReadAnnotation) // annotation ? { var cs = data.GetUInt32(offset, Endian.Little); offset += 4; - readExpansion = data.GetString(offset, cs); + readAnnotation = data.GetString(offset, cs); offset += cs; } - if (hasWriteExpansion) // expansion ? + if (hasWriteAnnotation) // annotation ? { var cs = data.GetUInt32(offset, Endian.Little); offset += 4; - writeExpansion = data.GetString(offset, cs); + writeAnnotation = data.GetString(offset, cs); offset += cs; } - var pt = new PropertyTemplate(od, propertyIndex++, name, inherited, valueType, readExpansion, writeExpansion, recordable); + var pt = new PropertyTemplate(od, propertyIndex++, name, inherited, valueType, readAnnotation, writeAnnotation, recordable); od.properties.Add(pt); } else if (type == 2) // Event { - string expansion = null; - var hasExpansion = ((data[offset] & 0x10) == 0x10); + string annotation = null; + var hasAnnotation = ((data[offset] & 0x10) == 0x10); var listenable = ((data[offset++] & 0x8) == 0x8); var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]); @@ -982,15 +982,15 @@ public class TypeTemplate offset += dts; - if (hasExpansion) // expansion ? + if (hasAnnotation) // annotation ? { var cs = data.GetUInt32(offset, Endian.Little); offset += 4; - expansion = data.GetString(offset, cs); + annotation = data.GetString(offset, cs); offset += cs; } - var et = new EventTemplate(od, eventIndex++, name, inherited, argType, expansion, listenable); + var et = new EventTemplate(od, eventIndex++, name, inherited, argType, annotation, listenable); od.events.Add(et); @@ -998,8 +998,8 @@ public class TypeTemplate // constant else if (type == 3) { - string expansion = null; - var hasExpansion = ((data[offset++] & 0x10) == 0x10); + string annotation = null; + var hasAnnotation = ((data[offset++] & 0x10) == 0x10); var name = data.GetString(offset + 1, data[offset]); offset += (uint)data[offset] + 1; @@ -1012,15 +1012,15 @@ public class TypeTemplate offset += dts; - if (hasExpansion) // expansion ? + if (hasAnnotation) // annotation ? { var cs = data.GetUInt32(offset, Endian.Little); offset += 4; - expansion = data.GetString(offset, cs); + annotation = data.GetString(offset, cs); offset += cs; } - var ct = new ConstantTemplate(od, eventIndex++, name, inherited, valueType, value.Result, expansion); + var ct = new ConstantTemplate(od, eventIndex++, name, inherited, valueType, value.Result, annotation); od.constants.Add(ct); } diff --git a/Test/MyResource.cs b/Test/MyResource.cs index 5b4e5e6..66a3423 100644 --- a/Test/MyResource.cs +++ b/Test/MyResource.cs @@ -11,7 +11,7 @@ namespace Test [Annotation("A", "B", "C", "D")] public partial class MyResource { - [Public] string description; + [Public][Annotation("Comment")] string description; [Public] int categoryId; } } diff --git a/Test/Program.cs b/Test/Program.cs index 0507605..dd97b9b 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -94,6 +94,10 @@ namespace Test { dynamic remote = await Warehouse.Get("iip://localhost/mem/service"); + var con = remote.Connection as DistributedConnection; + var template = await con.GetTemplateByClassName("Test.MyResource"); + + TestObjectProps(local, remote); var gr = await remote.GetGenericRecord(); @@ -184,5 +188,9 @@ namespace Test } } + + + + }