From 499f1e37d23931e911bd2a83902315c1dc37b051 Mon Sep 17 00:00:00 2001 From: Esiur Project Date: Sun, 5 Jun 2022 02:06:59 +0300 Subject: [PATCH] Generics workaround --- Esiur/Data/Codec.cs | 24 +++++------ Esiur/Data/RepresentationType.cs | 55 ++++++++++++------------- Esiur/Net/HTTP/HTTPServer.cs | 15 +------ Esiur/Resource/Template/TypeTemplate.cs | 34 +++++++++++---- Esiur/TODO | 3 +- Test/MyService.cs | 20 ++++++++- Test/Program.cs | 16 +++---- 7 files changed, 89 insertions(+), 78 deletions(-) diff --git a/Esiur/Data/Codec.cs b/Esiur/Data/Codec.cs index ac4b94c..3f8f9d5 100644 --- a/Esiur/Data/Codec.cs +++ b/Esiur/Data/Codec.cs @@ -284,7 +284,17 @@ public static class Codec } else { - if (type.IsGenericType) + if (Codec.ImplementsInterface(type, typeof(IResource))) + { + var (hdr, data) = DataSerializer.ResourceComposer(valueOrSource, connection); + return TransmissionType.Compose(hdr, data); + } + else if (Codec.ImplementsInterface(type, typeof(IRecord))) + { + var (hdr, data) = DataSerializer.RecordComposer(valueOrSource, connection); + return TransmissionType.Compose(hdr, data); + } + else if (type.IsGenericType) { var genericType = type.GetGenericTypeDefinition(); if (genericType == typeof(List<>)) @@ -326,17 +336,7 @@ public static class Codec return TransmissionType.Compose(hdr, data); //} - } - else if (Codec.ImplementsInterface(type, typeof(IResource))) - { - var (hdr, data) = DataSerializer.ResourceComposer(valueOrSource, connection); - return TransmissionType.Compose(hdr, data); - } - else if (Codec.ImplementsInterface(type, typeof(IRecord))) - { - var (hdr, data) = DataSerializer.RecordComposer(valueOrSource, connection); - return TransmissionType.Compose(hdr, data); - } + } else if (type.IsEnum) { var (hdr, data) = DataSerializer.EnumComposer(valueOrSource, connection); diff --git a/Esiur/Data/RepresentationType.cs b/Esiur/Data/RepresentationType.cs index c10d142..54bf778 100644 --- a/Esiur/Data/RepresentationType.cs +++ b/Esiur/Data/RepresentationType.cs @@ -168,13 +168,11 @@ namespace Esiur.Data public RepresentationType?[] SubTypes = new RepresentationType[3]; - public static RepresentationType? FromType(Type type)//, bool forceNullable = false) + public static RepresentationType? FromType(Type type) { - var nullable = false;// = forceNullable; - - //if (!forceNullable) - //{ + var nullable = false; + var nullType = System.Nullable.GetUnderlyingType(type); if (nullType != null) @@ -182,9 +180,30 @@ namespace Esiur.Data type = nullType; nullable = true; } - //} - if (type.IsGenericType) + if (type == typeof(IResource)) + return new RepresentationType(RepresentationTypeIdentifier.Resource, nullable); + else if (type == typeof(IRecord) || type == typeof(Record)) + return new RepresentationType(RepresentationTypeIdentifier.Record, nullable); + else if (type == typeof(Map)) + return new RepresentationType(RepresentationTypeIdentifier.Map, nullable); + else if (Codec.ImplementsInterface(type, typeof(IResource))) + { + return new RepresentationType( + RepresentationTypeIdentifier.TypedResource, + nullable, + TypeTemplate.GetTypeGuid(type) + ); + } + else if (Codec.ImplementsInterface(type, typeof(IRecord))) + { + return new RepresentationType( + RepresentationTypeIdentifier.TypedRecord, + nullable, + TypeTemplate.GetTypeGuid(type) + ); + } + else if (type.IsGenericType) { var genericType = type.GetGenericTypeDefinition(); if (genericType == typeof(List<>)) @@ -327,28 +346,6 @@ namespace Esiur.Data } } - else if (type == typeof(IResource)) - return new RepresentationType(RepresentationTypeIdentifier.Resource, nullable); - else if (type == typeof(IRecord) || type == typeof(Record)) - return new RepresentationType(RepresentationTypeIdentifier.Record, nullable); - else if (type == typeof(Map)) - return new RepresentationType(RepresentationTypeIdentifier.Map, nullable); - else if (Codec.ImplementsInterface(type, typeof(IResource))) - { - return new RepresentationType( - RepresentationTypeIdentifier.TypedResource, - nullable, - TypeTemplate.GetTypeGuid(type) - ); - } - else if (Codec.ImplementsInterface(type, typeof(IRecord))) - { - return new RepresentationType( - RepresentationTypeIdentifier.TypedRecord, - nullable, - TypeTemplate.GetTypeGuid(type) - ); - } else if (type.IsEnum) { return new RepresentationType(RepresentationTypeIdentifier.Enum, nullable, TypeTemplate.GetTypeGuid(type)); diff --git a/Esiur/Net/HTTP/HTTPServer.cs b/Esiur/Net/HTTP/HTTPServer.cs index bdbbc2f..fd40f69 100644 --- a/Esiur/Net/HTTP/HTTPServer.cs +++ b/Esiur/Net/HTTP/HTTPServer.cs @@ -190,20 +190,7 @@ public class HTTPServer : NetworkServer, IResource set; } - //[Attribute] - //public virtual uint Timeout - //{ - // get; - // set; - //} - - //[Attribute] - //public virtual uint Clock - //{ - // get; - // set; - //} - + [Attribute] public virtual uint MaxPost { diff --git a/Esiur/Resource/Template/TypeTemplate.cs b/Esiur/Resource/Template/TypeTemplate.cs index f82fc6f..3d70064 100644 --- a/Esiur/Resource/Template/TypeTemplate.cs +++ b/Esiur/Resource/Template/TypeTemplate.cs @@ -158,7 +158,7 @@ public class TypeTemplate } - public static Guid GetTypeGuid(Type type) => GetTypeGuid(type.FullName); + public static Guid GetTypeGuid(Type type) => GetTypeGuid(GetTypeClassName(type)); public static Guid GetTypeGuid(string typeName) { @@ -174,6 +174,11 @@ public class TypeTemplate return GetDistributedTypes(type.GetElementType()); else if (type.IsEnum) return new Type[] { type }; + else if (Codec.ImplementsInterface(type, typeof(IRecord)) + || Codec.ImplementsInterface(type, typeof(IResource))) + { + return new Type[] { type }; + } else if (type.IsGenericType) { var genericType = type.GetGenericTypeDefinition(); @@ -199,11 +204,7 @@ public class TypeTemplate return rt.ToArray(); } } - else if (Codec.ImplementsInterface(type, typeof(IRecord)) - || Codec.ImplementsInterface(type, typeof(IResource))) - { - return new Type[] { type }; - } + return new Type[0]; } @@ -354,6 +355,22 @@ public class TypeTemplate return type.Name + "?"; } + public static string GetTypeClassName(Type type, string separator = ".") + { + + if (type.IsGenericType) + { + var index = type.Name.IndexOf("`"); + var name = $"{type.Namespace}{separator}{((index > -1) ? type.Name.Substring(0, index) : type.Name)}Of"; + foreach (var t in type.GenericTypeArguments) + name += GetTypeClassName(t, "_"); + + return name; + } + else + return $"{type.Namespace}{separator}{type.Name}"; + } + public TypeTemplate(Type type, bool addToWarehouse = false) { if (Codec.InheritsClass(type, typeof(DistributedResource))) @@ -377,7 +394,7 @@ public class TypeTemplate DefinedType = type; - className = type.FullName; + className = GetTypeClassName(type); // set guid classId = GetTypeGuid(className); @@ -615,7 +632,6 @@ public class TypeTemplate ft.MethodInfo = mi; functions.Add(ft); - }; @@ -761,7 +777,7 @@ public class TypeTemplate { // find the first parent type that implements IResource var ParentDefinedType = ResourceProxy.GetBaseType(type.BaseType); - var parentId = GetTypeGuid(ParentDefinedType.FullName); + var parentId = GetTypeGuid(ParentDefinedType); b.AddUInt8((byte)(0x80 | (byte)templateType)) .AddGuid(classId) diff --git a/Esiur/TODO b/Esiur/TODO index 48008c5..b0b8683 100644 --- a/Esiur/TODO +++ b/Esiur/TODO @@ -1,3 +1,2 @@  -1- Bin -2- clean \ No newline at end of file +1- Generic Records/Resources \ No newline at end of file diff --git a/Test/MyService.cs b/Test/MyService.cs index 74929e8..10934d0 100644 --- a/Test/MyService.cs +++ b/Test/MyService.cs @@ -19,6 +19,15 @@ public enum SizeEnum:short XLarge = 22 } + +public class SearchResults : IRecord where T : IResource +{ + [Public] public int Offset { get; set; } + [Public] public int Needed { get; set; } + [Public] public int Total { get; set; } + [Public] public T[] Results { get; set; } +} + [Resource] public partial class MyService { @@ -29,6 +38,12 @@ public partial class MyService [Public] bool boolean = true; [Public] bool[] booleanArray = new bool[] { true, false, true, false, true }; + [Public] + public SearchResults GetRecords() + { + return new SearchResults() { Needed = 3, Offset = 10, Results = new MyResource[0], Total = 102 }; + } + [Public] byte uInt8Test = 8; [Public] byte? uInt8Null = null; [Public] byte[] uInt8Array = new byte[] { 0, 1, 2, 3, 4, 5 }; @@ -124,7 +139,7 @@ public partial class MyService [Public] public IResource[] Resources { get; set; } [Public] - public void Void() => + public void Void() => Console.WriteLine("Void()"); [Public] @@ -159,7 +174,8 @@ public partial class MyService [Public] public (int, string, double, bool) GetTuple4(int a1, string a2, double a3, bool a4) => (a1, a2, a3, a4); - [Public] public MyRecord SendRecord(MyRecord record) + [Public] + public MyRecord SendRecord(MyRecord record) { Console.WriteLine(record.ToString()); return record; diff --git a/Test/Program.cs b/Test/Program.cs index 667c7b7..9db709f 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -45,6 +45,9 @@ using System.Collections.Generic; namespace Test { + + + class Program { @@ -64,7 +67,7 @@ namespace Test service.Resource = res1; service.ChildResource = res3; - service.Resources = new MyResource[] { res1, res2, res1 , res3 }; + service.Resources = new MyResource[] { res1, res2, res1, res3 }; //web.MapGet("/{action}/{age}", (int age, string action, HTTPConnection sender) => //{ @@ -86,25 +89,18 @@ namespace Test } - enum aa - { - a, - b, - c, - d - } - - public static (int, string) tuple() => (33, "sss"); private static async void TestClient(IResource local) { dynamic remote = await Warehouse.Get("iip://localhost/mem/service"); TestObjectProps(local, remote); + var r = await remote.GetRecords(); var opt = await remote.Optional(new { a1 = 22, a2 = 33, a4 = "What?" }); Console.WriteLine(opt); + await remote.Void(); await remote.Connection("ss", 33); await remote.ConnectionOptional("Test 2", 88);