diff --git a/Esiur/Esiur.csproj b/Esiur/Esiur.csproj
index 662ed8d..8d4fbad 100644
--- a/Esiur/Esiur.csproj
+++ b/Esiur/Esiur.csproj
@@ -6,7 +6,7 @@
Ahmed Kh. Zamil
http://www.esiur.com
true
- 2.2.2
+ 2.2.3
https://github.com/esiur/esiur-dotnet
Ahmed Kh. Zamil
@@ -62,21 +62,21 @@
-
+
-
+
-
+
-
+
diff --git a/Esiur/Proxy/TemplateGenerator.cs b/Esiur/Proxy/TemplateGenerator.cs
index ef54093..888de20 100644
--- a/Esiur/Proxy/TemplateGenerator.cs
+++ b/Esiur/Proxy/TemplateGenerator.cs
@@ -15,6 +15,49 @@ public static class TemplateGenerator
{
internal static Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)");
+ //public static string ToLiteral(string valueTextForCompiler)
+ //{
+ // return SymbolDisplay.FormatLiteral(valueTextForCompiler, false);
+ //}
+
+ static string ToLiteral(string input)
+ {
+ var literal = new StringBuilder();
+ literal.Append("\"");
+ foreach (var c in input)
+ {
+ switch (c)
+ {
+ case '\"': literal.Append("\\\""); break;
+ case '\\': literal.Append(@"\\"); break;
+ case '\0': literal.Append(@"\0"); break;
+ case '\a': literal.Append(@"\a"); break;
+ case '\b': literal.Append(@"\b"); break;
+ case '\f': literal.Append(@"\f"); break;
+ case '\n': literal.Append(@"\n"); break;
+ case '\r': literal.Append(@"\r"); break;
+ case '\t': literal.Append(@"\t"); break;
+ case '\v': literal.Append(@"\v"); break;
+ default:
+ // ASCII printable character
+ if (c >= 0x20 && c <= 0x7e)
+ {
+ literal.Append(c);
+ // As UTF16 escaped character
+ }
+ else
+ {
+ literal.Append(@"\u");
+ literal.Append(((int)c).ToString("x4"));
+ }
+ break;
+ }
+ }
+ literal.Append("\"");
+ return literal.ToString();
+ }
+
+
internal static string GenerateRecord(TypeTemplate template, TypeTemplate[] templates)
{
var cls = template.ClassName.Split('.');
@@ -22,10 +65,15 @@ public static class TemplateGenerator
var nameSpace = string.Join(".", cls.Take(cls.Length - 1));
var className = cls.Last();
+
var rt = new StringBuilder();
rt.AppendLine("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
rt.AppendLine($"namespace { nameSpace} {{");
+
+ if (template.Annotation != null)
+ rt.AppendLine($"[Annotation({ToLiteral(template.Annotation)})]");
+
rt.AppendLine($"[Public] public class {className} : IRecord {{");
@@ -52,6 +100,10 @@ public static class TemplateGenerator
rt.AppendLine("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
rt.AppendLine($"namespace { nameSpace} {{");
+
+ if (template.Annotation != null)
+ rt.AppendLine($"[Annotation({ToLiteral(template.Annotation)})]");
+
rt.AppendLine($"[Public] public enum {className} {{");
rt.AppendLine(String.Join(",\r\n", template.Constants.Select(x => $"{x.Name}={x.Value}")));
@@ -213,6 +265,9 @@ public static class TemplateGenerator
rt.AppendLine("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
rt.AppendLine($"namespace { nameSpace} {{");
+ if (template.Annotation != null)
+ rt.AppendLine($"[Annotation({ToLiteral(template.Annotation)})]");
+
// extends
if (template.ParentId == null)
rt.AppendLine($"public class {className} : DistributedResource {{");
diff --git a/Esiur/Resource/AnnotationAttribute.cs b/Esiur/Resource/AnnotationAttribute.cs
index 28d477c..2372e8c 100644
--- a/Esiur/Resource/AnnotationAttribute.cs
+++ b/Esiur/Resource/AnnotationAttribute.cs
@@ -4,7 +4,7 @@ using System.Text;
namespace Esiur.Resource;
-[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event)]
+[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event)]
public class AnnotationAttribute : Attribute
{
@@ -13,4 +13,8 @@ public class AnnotationAttribute : Attribute
{
this.Annotation = annotation;
}
+ public AnnotationAttribute(params string[] annotations)
+ {
+ this.Annotation = String.Join("\n", annotations);
+ }
}
diff --git a/Esiur/Resource/Template/TypeTemplate.cs b/Esiur/Resource/Template/TypeTemplate.cs
index 3d70064..5c4c06f 100644
--- a/Esiur/Resource/Template/TypeTemplate.cs
+++ b/Esiur/Resource/Template/TypeTemplate.cs
@@ -25,6 +25,8 @@ public class TypeTemplate
protected Guid classId;
protected Guid? parentId;
+ public string Annotation { get; set; }
+
string className;
List members = new List();
List functions = new List();
@@ -157,7 +159,6 @@ public class TypeTemplate
}
-
public static Guid GetTypeGuid(Type type) => GetTypeGuid(GetTypeClassName(type));
public static Guid GetTypeGuid(string typeName)
@@ -403,6 +404,7 @@ public class TypeTemplate
Warehouse.PutTemplate(this);
+
PropertyInfo[] propsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
EventInfo[] eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); // | BindingFlags.DeclaredOnly);
@@ -772,31 +774,37 @@ public class TypeTemplate
// find the first parent type that implements IResource
+ var hasParent = HasParent(type);
+ var classAnnotation = type.GetCustomAttribute(false);
+ var hasAnnotation = classAnnotation != null && classAnnotation.Annotation != null;
- if (HasParent(type))
+ var classNameBytes = DC.ToBytes(className);
+
+ b.AddUInt8((byte)((hasParent ? 0x80 : 0) | (hasAnnotation ? 0x40 : 0x0) | (byte)templateType))
+ .AddGuid(classId)
+ .AddUInt8((byte)classNameBytes.Length)
+ .AddUInt8Array(classNameBytes);
+
+ if (hasParent)
{
// find the first parent type that implements IResource
var ParentDefinedType = ResourceProxy.GetBaseType(type.BaseType);
var parentId = GetTypeGuid(ParentDefinedType);
-
- b.AddUInt8((byte)(0x80 | (byte)templateType))
- .AddGuid(classId)
- .AddUInt8((byte)className.Length)
- .AddString(className)
- .AddGuid(parentId)
- .AddInt32(version)
- .AddUInt16((ushort)members.Count);
+ b.AddGuid(parentId);
}
- else
+
+ if (hasAnnotation)
{
- b.AddUInt8((byte)templateType)
- .AddGuid(classId)
- .AddUInt8((byte)className.Length)
- .AddString(className)
- .AddInt32(version)
- .AddUInt16((ushort)members.Count);
+ var classAnnotationBytes = DC.ToBytes(classAnnotation.Annotation);
+ b.AddUInt16((ushort)classAnnotationBytes.Length)
+ .AddUInt8Array(classAnnotationBytes);
+
+ Annotation = classAnnotation.Annotation;
}
+ b.AddInt32(version)
+ .AddUInt16((ushort)members.Count);
+
foreach (var ft in functions)
b.AddUInt8Array(ft.Compose());
foreach (var pt in properties)
@@ -848,6 +856,8 @@ public class TypeTemplate
od.content = data.Clip(offset, contentLength);
var hasParent = (data[offset] & 0x80) > 0;
+ var hasAnnotation = (data[offset] & 0x40) > 0;
+
od.templateType = (TemplateType)(data[offset++] & 0xF);
od.classId = data.GetGuid(offset);
@@ -862,6 +872,14 @@ public class TypeTemplate
offset += 16;
}
+ if (hasAnnotation)
+ {
+ var len = data.GetUInt16(offset, Endian.Little);
+ offset += 2;
+ od.Annotation = data.GetString(offset, len);
+ offset += len;
+ }
+
od.version = data.GetInt32(offset, Endian.Little);
offset += 4;
diff --git a/Test/MyResource.cs b/Test/MyResource.cs
index 937e1a1..5b4e5e6 100644
--- a/Test/MyResource.cs
+++ b/Test/MyResource.cs
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
namespace Test
{
[Resource]
+ [Annotation("A", "B", "C", "D")]
public partial class MyResource
{
[Public] string description;
diff --git a/Test/Program.cs b/Test/Program.cs
index 6b7ccd4..0507605 100644
--- a/Test/Program.cs
+++ b/Test/Program.cs
@@ -53,7 +53,7 @@ namespace Test
static async Task Main(string[] args)
{
-
+
// Create stores to keep objects.
var system = await Warehouse.Put("mem", new MemoryStore());
var server = await Warehouse.Put("mem/server", new DistributedServer());