mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-01-27 01:20:39 +00:00
IDynamicResource Added
This commit is contained in:
@@ -4,7 +4,7 @@ using System.Text;
|
||||
|
||||
namespace Esiur.Resource;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event, AllowMultiple = true)]
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event | AttributeTargets.Parameter, AllowMultiple = true)]
|
||||
public class AnnotationAttribute : Attribute
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ public class AnnotationAttribute : Attribute
|
||||
|
||||
public AnnotationAttribute(string annotation)
|
||||
{
|
||||
Key = null;
|
||||
Key = "";
|
||||
Value = annotation;
|
||||
}
|
||||
public AnnotationAttribute(string key, string value)
|
||||
|
||||
@@ -116,58 +116,6 @@ public class Instance
|
||||
}
|
||||
|
||||
return rt;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
var st = new Structure();
|
||||
|
||||
if (attributes == null)
|
||||
{
|
||||
var clone = this.attributes.Keys.ToList();
|
||||
clone.Add("managers");
|
||||
attributes = clone.ToArray();// this.attributes.Keys.ToList().Add("managers");
|
||||
}
|
||||
|
||||
foreach (var attr in attributes)
|
||||
{
|
||||
if (attr == "name")
|
||||
st["name"] = this.name;
|
||||
else if (attr == "managers")
|
||||
{
|
||||
var mngrs = new List<Structure>();
|
||||
|
||||
foreach (var manager in this.managers)
|
||||
mngrs.Add(new Structure()
|
||||
{
|
||||
["type"] = manager.GetType().FullName + "," + manager.GetType().GetTypeInfo().Assembly.GetName().Name,
|
||||
["settings"] = manager.Settings
|
||||
});
|
||||
|
||||
st["managers"] = mngrs.ToArray();
|
||||
}
|
||||
else if (attr == "parents")
|
||||
{
|
||||
//st["parents"] = parents.ToArray();
|
||||
}
|
||||
else if (attr == "children")
|
||||
{
|
||||
//st["children"] = children.ToArray();
|
||||
}
|
||||
else if (attr == "childrenCount")
|
||||
{
|
||||
//st["childrenCount"] = children.Count;
|
||||
}
|
||||
else if (attr == "type")
|
||||
{
|
||||
st["type"] = resource.GetType().FullName;
|
||||
}
|
||||
else
|
||||
st[attr] = this.attributes[attr];
|
||||
}
|
||||
|
||||
return st;
|
||||
*/
|
||||
}
|
||||
|
||||
public bool SetAttributes(Map<string, object> attributes, bool clearAttributes = false)
|
||||
@@ -454,17 +402,21 @@ public class Instance
|
||||
/// <returns></returns>
|
||||
public PropertyValue[] Serialize()
|
||||
{
|
||||
IResource res;
|
||||
|
||||
if (!resource.TryGetTarget(out res))
|
||||
throw new Exception("Resource no longer available.");
|
||||
|
||||
|
||||
if (res is IDynamicResource dynamicResource)
|
||||
return dynamicResource.SerializeResource();
|
||||
|
||||
var props = new List<PropertyValue>();
|
||||
|
||||
foreach (var pt in template.Properties)
|
||||
{
|
||||
IResource res;
|
||||
|
||||
if (resource.TryGetTarget(out res))
|
||||
{
|
||||
var rt = pt.PropertyInfo.GetValue(res, null);
|
||||
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
|
||||
}
|
||||
var rt = pt.PropertyInfo.GetValue(res, null);
|
||||
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
|
||||
}
|
||||
|
||||
return props.ToArray();
|
||||
@@ -476,93 +428,31 @@ public class Instance
|
||||
/// <returns></returns>
|
||||
public Map<byte, PropertyValue> SerializeAfter(ulong age = 0)
|
||||
{
|
||||
IResource res;
|
||||
|
||||
if (!resource.TryGetTarget(out res))
|
||||
throw new Exception("Resource no longer available.");
|
||||
|
||||
if (res is IDynamicResource dynamicResource)
|
||||
return dynamicResource.SerializeResourceAfter(age);
|
||||
|
||||
var props = new Map<byte, PropertyValue>();
|
||||
|
||||
foreach (var pt in template.Properties)
|
||||
{
|
||||
IResource res;
|
||||
if (resource.TryGetTarget(out res))
|
||||
if (res.Instance.GetAge(pt.Index) > age)
|
||||
{
|
||||
if (res.Instance.GetAge(pt.Index) > age)
|
||||
{
|
||||
var rt = pt.PropertyInfo.GetValue(res, null);
|
||||
props.Add(pt.Index,
|
||||
new PropertyValue(rt,
|
||||
ages[pt.Index],
|
||||
modificationDates[pt.Index]));
|
||||
}
|
||||
var rt = pt.PropertyInfo.GetValue(res, null);
|
||||
props.Add(pt.Index,
|
||||
new PropertyValue(rt,
|
||||
ages[pt.Index],
|
||||
modificationDates[pt.Index]));
|
||||
}
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
/*
|
||||
public bool Deserialize(byte[] data, uint offset, uint length)
|
||||
{
|
||||
|
||||
var props = Codec.ParseValues(data, offset, length);
|
||||
Deserialize(props);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
public byte[] Serialize(bool includeLength = false, DistributedConnection sender = null)
|
||||
{
|
||||
|
||||
//var bl = new BinaryList();
|
||||
List<object> props = new List<object>();
|
||||
|
||||
foreach (var pt in template.Properties)
|
||||
{
|
||||
|
||||
var pi = resource.GetType().GetProperty(pt.Name);
|
||||
|
||||
var rt = pi.GetValue(resource, null);
|
||||
|
||||
// this is a cool hack to let the property know the sender
|
||||
if (rt is Func<DistributedConnection, object>)
|
||||
rt = (rt as Func<DistributedConnection, object>)(sender);
|
||||
|
||||
props.Add(rt);
|
||||
|
||||
}
|
||||
|
||||
if (includeLength)
|
||||
{
|
||||
return Codec.Compose(props.ToArray(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rt = Codec.Compose(props.ToArray(), false);
|
||||
return DC.Clip(rt, 4, (uint)(rt.Length - 4));
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] StorageSerialize()
|
||||
{
|
||||
|
||||
var props = new List<object>();
|
||||
|
||||
foreach(var pt in template.Properties)
|
||||
{
|
||||
if (!pt.Storable)
|
||||
continue;
|
||||
|
||||
var pi = resource.GetType().GetProperty(pt.Name);
|
||||
|
||||
if (!pi.CanWrite)
|
||||
continue;
|
||||
|
||||
var rt = pi.GetValue(resource, null);
|
||||
|
||||
props.Add(rt);
|
||||
|
||||
}
|
||||
|
||||
return Codec.Compose(props.ToArray(), false);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// If True, the instance can be stored to disk.
|
||||
@@ -619,7 +509,7 @@ public class Instance
|
||||
return;
|
||||
|
||||
object value;
|
||||
if (GetPropertyValue(propertyName, out value))
|
||||
if (TryGetPropertyValue(propertyName, out value))
|
||||
{
|
||||
var pt = template.GetPropertyTemplateByName(propertyName);
|
||||
EmitModification(pt, value);
|
||||
@@ -675,66 +565,37 @@ public class Instance
|
||||
/// <param name="name">Property name</param>
|
||||
/// <param name="value">Output value</param>
|
||||
/// <returns>True, if the resource has the property.</returns>
|
||||
public bool GetPropertyValue(string name, out object value)
|
||||
public bool TryGetPropertyValue(string name, out object value)
|
||||
{
|
||||
/*
|
||||
#if NETSTANDARD
|
||||
PropertyInfo pi = resource.GetType().GetTypeInfo().GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
||||
|
||||
#else
|
||||
PropertyInfo pi = resource.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
|
||||
#endif
|
||||
*/
|
||||
|
||||
var pt = template.GetPropertyTemplateByName(name);
|
||||
|
||||
if (pt != null && pt.PropertyInfo != null)
|
||||
IResource res;
|
||||
if (resource.TryGetTarget(out res))
|
||||
{
|
||||
/*
|
||||
#if NETSTANDARD
|
||||
object[] ca = pi.GetCustomAttributes(typeof(ResourceProperty), false).ToArray();
|
||||
|
||||
#else
|
||||
object[] ca = pi.GetCustomAttributes(typeof(ResourceProperty), false);
|
||||
#endif
|
||||
|
||||
if (ca.Length > 0)
|
||||
if (res is IDynamicResource dynamicResource)
|
||||
{
|
||||
value = pi.GetValue(resource, null);
|
||||
//if (value is Func<IManager, object>)
|
||||
// value = (value as Func<IManager, object>)(sender);
|
||||
value = dynamicResource.GetResourceProperty(pt.Index);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
IResource res;
|
||||
if (resource.TryGetTarget(out res))
|
||||
value = pt.PropertyInfo.GetValue(res, null);
|
||||
else
|
||||
else if (pt != null && pt.PropertyInfo != null)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
value = pt.PropertyInfo.GetValue(res, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public bool Inherit
|
||||
public object GetPropertyValueOrDefault(string name, object defaultValue = null)
|
||||
{
|
||||
get { return inherit; }
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// List of parents.
|
||||
/// </summary>
|
||||
//public AutoList<IResource, Instance> Parents => parents;
|
||||
object value;
|
||||
if (TryGetPropertyValue(name, out value))
|
||||
return value;
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store responsible for creating and keeping the resource.
|
||||
@@ -746,11 +607,6 @@ public class Instance
|
||||
|
||||
public bool IsDestroyed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of children.
|
||||
/// </summary>
|
||||
// public AutoList<IResource, Instance> Children => children;
|
||||
|
||||
/// <summary>
|
||||
/// The unique and permanent link to the resource.
|
||||
/// </summary>
|
||||
@@ -793,35 +649,6 @@ public class Instance
|
||||
return new AsyncBag<T>(default(T[]));
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.store != null)
|
||||
return this.store.Link(this.resource);
|
||||
else
|
||||
{
|
||||
var l = new List<string>();
|
||||
//l.Add(name);
|
||||
|
||||
var p = this.resource; // parents.First();
|
||||
|
||||
while (true)
|
||||
{
|
||||
l.Insert(0, p.Instance.name);
|
||||
|
||||
if (p.Instance.parents.Count == 0)
|
||||
break;
|
||||
|
||||
p = p.Instance.parents.First();
|
||||
}
|
||||
|
||||
return String.Join("/", l.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
*
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Instance name.
|
||||
@@ -913,7 +740,7 @@ public class Instance
|
||||
/// <param name="name">Name of the instance.</param>
|
||||
/// <param name="resource">Resource to manage.</param>
|
||||
/// <param name="store">Store responsible for the resource.</param>
|
||||
public Instance(Warehouse warehouse, uint id, string name, IResource resource, IStore store, TypeTemplate customTemplate = null, ulong age = 0)
|
||||
public Instance(Warehouse warehouse, uint id, string name, IResource resource, IStore store, ulong age = 0)
|
||||
{
|
||||
this.Warehouse = warehouse;
|
||||
this.store = store;
|
||||
@@ -933,10 +760,14 @@ public class Instance
|
||||
|
||||
resource.OnDestroy += Resource_OnDestroy;
|
||||
|
||||
if (customTemplate != null)
|
||||
this.template = customTemplate;
|
||||
if (resource is IDynamicResource dynamicResource)
|
||||
{
|
||||
this.template = dynamicResource.ResourceTemplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.template = Warehouse.GetTemplateByType(resource.GetType());
|
||||
}
|
||||
|
||||
// set ages
|
||||
for (byte i = 0; i < template.Properties.Length; i++)
|
||||
@@ -1020,34 +851,6 @@ public class Instance
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//IQueryable<IResource> Children => store.GetChildren(this);
|
||||
|
||||
|
||||
/*
|
||||
* private void Children_OnRemoved(Instance parent, IResource value)
|
||||
{
|
||||
value.Instance.parents.Remove(resource);
|
||||
}
|
||||
|
||||
private void Children_OnAdd(Instance parent, IResource value)
|
||||
{
|
||||
if (!value.Instance.parents.Contains(resource))
|
||||
value.Instance.parents.Add(resource);
|
||||
}
|
||||
|
||||
private void Parents_OnRemoved(Instance parent, IResource value)
|
||||
{
|
||||
value.Instance.children.Remove(resource);
|
||||
}
|
||||
|
||||
private void Parents_OnAdd(Instance parent, IResource value)
|
||||
{
|
||||
if (!value.Instance.children.Contains(resource))
|
||||
value.Instance.children.Add(resource);
|
||||
}
|
||||
*/
|
||||
|
||||
private void Resource_OnDestroy(object sender)
|
||||
{
|
||||
IsDestroyed = true;
|
||||
|
||||
@@ -30,20 +30,30 @@ public class ArgumentTemplate
|
||||
offset += cs;
|
||||
var (size, type) = TRU.Parse(data, offset);
|
||||
|
||||
offset += size;
|
||||
|
||||
Map<string, string> annotations = null;
|
||||
|
||||
if (hasAnnotations)
|
||||
{
|
||||
var acs = data.GetUInt32(offset, Endian.Little);
|
||||
offset += 2;
|
||||
//var acs = data.GetUInt32(offset, Endian.Little);
|
||||
//offset += 2;
|
||||
var (l, a) = Codec.ParseSync(data, offset, null);
|
||||
// for saftey, Map<string, string> might change in the future
|
||||
if (a is Map<string, string> ann)
|
||||
annotations = ann;
|
||||
|
||||
cs += l;
|
||||
}
|
||||
|
||||
return (cs + 2 + size, new ArgumentTemplate(name, index, type, optional, annotations));
|
||||
return (cs + 2 + size, new ArgumentTemplate()
|
||||
{
|
||||
Name = name,
|
||||
Index = index,
|
||||
Type = type,
|
||||
Optional = optional,
|
||||
Annotations = annotations
|
||||
});
|
||||
}
|
||||
|
||||
public ArgumentTemplate()
|
||||
@@ -51,15 +61,7 @@ public class ArgumentTemplate
|
||||
|
||||
}
|
||||
|
||||
public ArgumentTemplate(string name, int index, TRU type, bool optional, Map<string, string> annotations)
|
||||
{
|
||||
Name = name;
|
||||
Index = index;
|
||||
Type = type;
|
||||
Optional = optional;
|
||||
Annotations = annotations;
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Optional)
|
||||
@@ -90,10 +92,8 @@ public class ArgumentTemplate
|
||||
.AddUInt8((byte)name.Length)
|
||||
.AddUInt8Array(name)
|
||||
.AddUInt8Array(Type.Compose())
|
||||
.AddUInt32((ushort)exp.Length)
|
||||
.AddUInt8Array(exp)
|
||||
.ToArray();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Esiur.Resource.Template;
|
||||
|
||||
public class AttributeTemplate : MemberTemplate
|
||||
{
|
||||
|
||||
public PropertyInfo PropertyInfo
|
||||
{
|
||||
get;
|
||||
@@ -17,16 +18,14 @@ public class AttributeTemplate : MemberTemplate
|
||||
}
|
||||
|
||||
|
||||
public AttributeTemplate(TypeTemplate template, byte index, string name, bool inherited)
|
||||
: base(template, index, name, inherited)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static AttributeTemplate MakeAttributeTemplate(Type type, PropertyInfo pi, byte index = 0, string customName = null, TypeTemplate typeTemplate = null)
|
||||
{
|
||||
var at = new AttributeTemplate(typeTemplate, index, customName, pi.DeclaringType != type);
|
||||
at.PropertyInfo = pi;
|
||||
return at;
|
||||
return new AttributeTemplate()
|
||||
{
|
||||
Index = index,
|
||||
Inherited = pi.DeclaringType != type,
|
||||
Name = customName,
|
||||
PropertyInfo = pi
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,33 +9,59 @@ namespace Esiur.Resource.Template;
|
||||
|
||||
public class ConstantTemplate : MemberTemplate
|
||||
{
|
||||
public readonly object Value;
|
||||
public object Value { get; set; }
|
||||
|
||||
public Map<string, string> Annotations;
|
||||
public readonly TRU ValueType;
|
||||
public Map<string, string> Annotations { get; set; }
|
||||
public TRU ValueType { get; set; }
|
||||
|
||||
public FieldInfo FieldInfo { get; set; }
|
||||
public FieldInfo FieldInfo { get; set; }
|
||||
|
||||
public ConstantTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU valueType, object value, Map<string, string> annotations)
|
||||
: base(template, index, name, inherited)
|
||||
|
||||
public static (uint, ConstantTemplate) Parse(byte[] data, uint offset, byte index, bool inherited)
|
||||
{
|
||||
Annotations = annotations;
|
||||
ValueType = valueType;
|
||||
Value = value;
|
||||
//try
|
||||
//{
|
||||
// Codec.Compose(value, null);
|
||||
// Value = value;
|
||||
//}
|
||||
//catch
|
||||
//{
|
||||
// throw new Exception($"Constant `{template.ClassName}.{name}` can't be serialized.");
|
||||
//}
|
||||
var oOffset = offset;
|
||||
|
||||
var hasAnnotation = ((data[offset++] & 0x10) == 0x10);
|
||||
|
||||
var name = data.GetString(offset + 1, data[offset]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
var (dts, valueType) = TRU.Parse(data, offset);
|
||||
|
||||
offset += dts;
|
||||
|
||||
(dts, var value) = Codec.ParseSync(data, offset, Warehouse.Default);
|
||||
|
||||
offset += dts;
|
||||
|
||||
Map<string, string> annotations = null;
|
||||
|
||||
// arguments
|
||||
if (hasAnnotation) // Annotation ?
|
||||
{
|
||||
var (len, anns) = Codec.ParseSync(data, offset, null);
|
||||
|
||||
if (anns is Map<string, string> map)
|
||||
annotations = map;
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return (offset - oOffset, new ConstantTemplate()
|
||||
{
|
||||
Index = index,
|
||||
Name = name,
|
||||
Inherited = inherited,
|
||||
ValueType = valueType,
|
||||
Value = value,
|
||||
Annotations = annotations
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public override byte[] Compose()
|
||||
public byte[] Compose()
|
||||
{
|
||||
var name = base.Compose();
|
||||
var name = DC.ToBytes(Name);
|
||||
|
||||
var hdr = Inherited ? (byte)0x80 : (byte)0;
|
||||
|
||||
@@ -93,10 +119,17 @@ public class ConstantTemplate : MemberTemplate
|
||||
}
|
||||
|
||||
|
||||
var ct = new ConstantTemplate(typeTemplate, index, customName ?? ci.Name, ci.DeclaringType != type, valueType, value, annotations);
|
||||
ct.FieldInfo = ci;
|
||||
|
||||
return ct;
|
||||
return new ConstantTemplate()
|
||||
{
|
||||
Name = customName,
|
||||
Index = index,
|
||||
Inherited = ci.DeclaringType != type,
|
||||
ValueType = valueType,
|
||||
Value = value,
|
||||
FieldInfo = ci,
|
||||
Annotations = annotations,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Esiur.Resource.Template;
|
||||
|
||||
public class EventTemplate : MemberTemplate
|
||||
{
|
||||
|
||||
public Map<string, string> Annotations
|
||||
{
|
||||
get;
|
||||
@@ -29,9 +30,48 @@ public class EventTemplate : MemberTemplate
|
||||
|
||||
public TRU ArgumentType { get; set; }
|
||||
|
||||
public override byte[] Compose()
|
||||
|
||||
public static (uint, EventTemplate) Parse(byte[] data, uint offset, byte index, bool inherited)
|
||||
{
|
||||
var name = base.Compose();
|
||||
var oOffset = offset;
|
||||
|
||||
var hasAnnotation = ((data[offset] & 0x10) == 0x10);
|
||||
var subscribable = ((data[offset++] & 0x8) == 0x8);
|
||||
|
||||
var name = data.GetString(offset + 1, data[offset]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
var (dts, argType) = TRU.Parse(data, offset);
|
||||
|
||||
offset += dts;
|
||||
|
||||
// Annotation ?
|
||||
Map<string, string> annotations = null;
|
||||
|
||||
if (hasAnnotation)
|
||||
{
|
||||
var (len, anns) = Codec.ParseSync(data, offset, null);
|
||||
|
||||
if (anns is Map<string, string> map)
|
||||
annotations = map;
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return (offset - oOffset, new EventTemplate()
|
||||
{
|
||||
Index = index,
|
||||
Name = name,
|
||||
Inherited = inherited,
|
||||
ArgumentType = argType,
|
||||
Subscribable = subscribable,
|
||||
Annotations = annotations
|
||||
});
|
||||
}
|
||||
|
||||
public byte[] Compose()
|
||||
{
|
||||
var name = Name.ToBytes();
|
||||
|
||||
var hdr = Inherited ? (byte)0x80 : (byte)0;
|
||||
|
||||
@@ -62,13 +102,13 @@ public class EventTemplate : MemberTemplate
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public EventTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU argumentType, Map<string, string> annotations = null, bool subscribable = false)
|
||||
: base(template, index, name, inherited)
|
||||
{
|
||||
this.Annotations = annotations;
|
||||
this.Subscribable = subscribable;
|
||||
this.ArgumentType = argumentType;
|
||||
}
|
||||
//public EventTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU argumentType, Map<string, string> annotations = null, bool subscribable = false)
|
||||
// : base(template, index, name, inherited)
|
||||
//{
|
||||
// this.Annotations = annotations;
|
||||
// this.Subscribable = subscribable;
|
||||
// this.ArgumentType = argumentType;
|
||||
//}
|
||||
|
||||
public static EventTemplate MakeEventTemplate(Type type, EventInfo ei, byte index = 0, string customName = null, TypeTemplate typeTemplate = null)
|
||||
{
|
||||
@@ -121,21 +161,26 @@ public class EventTemplate : MemberTemplate
|
||||
evtType.SetNull(nullableAttrFlags);
|
||||
}
|
||||
|
||||
var et = new EventTemplate(typeTemplate, index, customName ?? ei.Name, ei.DeclaringType != type, evtType);
|
||||
et.EventInfo = ei;
|
||||
|
||||
Map<string, string> annotations = null;
|
||||
|
||||
if (annotationAttrs != null && annotationAttrs.Count() > 0)
|
||||
{
|
||||
et.Annotations = new Map<string, string>();
|
||||
annotations = new Map<string, string>();
|
||||
foreach (var attr in annotationAttrs)
|
||||
et.Annotations.Add(attr.Key, attr.Value);
|
||||
annotations.Add(attr.Key, attr.Value);
|
||||
}
|
||||
|
||||
if (subscribableAttr != null)
|
||||
et.Subscribable = true;
|
||||
|
||||
return et;
|
||||
return new EventTemplate()
|
||||
{
|
||||
Name = customName ?? ei.Name,
|
||||
ArgumentType = evtType,
|
||||
Index = index,
|
||||
Inherited = ei.DeclaringType != type,
|
||||
Annotations = annotations,
|
||||
EventInfo = ei,
|
||||
Subscribable = subscribableAttr != null
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Esiur.Resource.Template;
|
||||
|
||||
public class FunctionTemplate : MemberTemplate
|
||||
{
|
||||
|
||||
@@ -38,10 +39,61 @@ public class FunctionTemplate : MemberTemplate
|
||||
}
|
||||
|
||||
|
||||
public override byte[] Compose()
|
||||
public static (uint, FunctionTemplate) Parse(byte[] data, uint offset, byte index, bool inherited)
|
||||
{
|
||||
|
||||
var name = base.Compose();
|
||||
var oOffset = offset;
|
||||
|
||||
var isStatic = ((data[offset] & 0x4) == 0x4);
|
||||
var hasAnnotation = ((data[offset++] & 0x10) == 0x10);
|
||||
|
||||
var name = data.GetString(offset + 1, data[offset]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
// return type
|
||||
var (rts, returnType) = TRU.Parse(data, offset);
|
||||
offset += rts;
|
||||
|
||||
// arguments count
|
||||
var argsCount = data[offset++];
|
||||
List<ArgumentTemplate> arguments = new();
|
||||
|
||||
for (var a = 0; a < argsCount; a++)
|
||||
{
|
||||
var (cs, argType) = ArgumentTemplate.Parse(data, offset, a);
|
||||
arguments.Add(argType);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
Map<string, string> annotations = null;
|
||||
|
||||
// arguments
|
||||
if (hasAnnotation) // Annotation ?
|
||||
{
|
||||
var (len, anns) = Codec.ParseSync(data, offset, null);
|
||||
|
||||
if (anns is Map<string, string> map)
|
||||
annotations = map;
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return (offset - oOffset, new FunctionTemplate()
|
||||
{
|
||||
Index = index,
|
||||
Name = name,
|
||||
Arguments = arguments.ToArray(),
|
||||
IsStatic = isStatic,
|
||||
Inherited = inherited,
|
||||
Annotations = annotations,
|
||||
ReturnType = returnType,
|
||||
});
|
||||
}
|
||||
|
||||
public byte[] Compose()
|
||||
{
|
||||
|
||||
var name = DC.ToBytes(Name);
|
||||
|
||||
var bl = new BinaryList()
|
||||
.AddUInt8((byte)name.Length)
|
||||
@@ -56,8 +108,7 @@ public class FunctionTemplate : MemberTemplate
|
||||
if (Annotations != null)
|
||||
{
|
||||
var exp = Codec.Compose(Annotations, null, null);// DC.ToBytes(Annotation);
|
||||
bl.AddInt32(exp.Length)
|
||||
.AddUInt8Array(exp);
|
||||
bl.AddUInt8Array(exp);
|
||||
bl.InsertUInt8(0, (byte)((Inherited ? (byte)0x90 : (byte)0x10) | (IsStatic ? 0x4 : 0)));
|
||||
}
|
||||
else
|
||||
@@ -66,14 +117,14 @@ public class FunctionTemplate : MemberTemplate
|
||||
return bl.ToArray();
|
||||
}
|
||||
|
||||
public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, bool isStatic, ArgumentTemplate[] arguments, TRU returnType, Map<string, string> annotations = null)
|
||||
: base(template, index, name, inherited)
|
||||
{
|
||||
this.Arguments = arguments;
|
||||
this.ReturnType = returnType;
|
||||
this.Annotations = annotations;
|
||||
this.IsStatic = isStatic;
|
||||
}
|
||||
//public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, bool isStatic, ArgumentTemplate[] arguments, TRU returnType, Map<string, string> annotations = null)
|
||||
// : base(template, index, name, inherited)
|
||||
//{
|
||||
// this.Arguments = arguments;
|
||||
// this.ReturnType = returnType;
|
||||
// this.Annotations = annotations;
|
||||
// this.IsStatic = isStatic;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
@@ -99,7 +150,10 @@ public class FunctionTemplate : MemberTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
rtType = TRU.FromType(mi.ReturnType);
|
||||
if (mi.ReturnType == typeof(Task))
|
||||
rtType = TRU.FromType(null);
|
||||
else
|
||||
rtType = TRU.FromType(mi.ReturnType);
|
||||
}
|
||||
|
||||
if (rtType == null)
|
||||
@@ -162,7 +216,7 @@ public class FunctionTemplate : MemberTemplate
|
||||
|
||||
if (args.Length > 0)
|
||||
{
|
||||
if (args.Last().ParameterType == typeof(DistributedConnection)
|
||||
if (args.Last().ParameterType == typeof(DistributedConnection)
|
||||
|| args.Last().ParameterType == typeof(InvocationContext))
|
||||
args = args.Take(args.Count() - 1).ToArray();
|
||||
}
|
||||
@@ -219,32 +273,35 @@ public class FunctionTemplate : MemberTemplate
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
var fn = customName ?? mi.Name;
|
||||
|
||||
var ft = new FunctionTemplate(typeTemplate, index, fn, mi.DeclaringType != type,
|
||||
mi.IsStatic,
|
||||
arguments, rtType);
|
||||
|
||||
Map<string, string> annotations = null;
|
||||
|
||||
if (annotationAttrs != null && annotationAttrs.Count() > 0)
|
||||
{
|
||||
ft.Annotations = new Map<string, string>();
|
||||
annotations = new Map<string, string>();
|
||||
foreach (var attr in annotationAttrs)
|
||||
ft.Annotations.Add(attr.Key, attr.Value);
|
||||
annotations.Add(attr.Key, attr.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ft.Annotations = new Map<string, string>();
|
||||
ft.Annotations.Add(null, "(" + String.Join(",",
|
||||
annotations = new Map<string, string>();
|
||||
annotations.Add("", "(" + 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);
|
||||
return new FunctionTemplate()
|
||||
{
|
||||
Name = customName ?? mi.Name,
|
||||
Index = index,
|
||||
Inherited = mi.DeclaringType != type,
|
||||
IsStatic = mi.IsStatic,
|
||||
ReturnType = rtType,
|
||||
Arguments = arguments,
|
||||
MethodInfo = mi,
|
||||
Annotations = annotations
|
||||
};
|
||||
|
||||
return ft;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -40,19 +40,19 @@ public class MemberData
|
||||
return rt;
|
||||
}
|
||||
|
||||
public string? GetAnnotation()
|
||||
{
|
||||
string? rt = null;
|
||||
var md = this;
|
||||
while (md != null)
|
||||
{
|
||||
var annotationAttr = md.Info.GetCustomAttribute<AnnotationAttribute>();
|
||||
if (annotationAttr != null)
|
||||
rt = annotationAttr.Annotation;
|
||||
md = md.Child;
|
||||
}
|
||||
//public string? GetAnnotation()
|
||||
//{
|
||||
// string? rt = null;
|
||||
// var md = this;
|
||||
// while (md != null)
|
||||
// {
|
||||
// var annotationAttr = md.Info.GetCustomAttribute<AnnotationAttribute>();
|
||||
// if (annotationAttr != null)
|
||||
// rt = annotationAttr.Annotation;
|
||||
// md = md.Child;
|
||||
// }
|
||||
|
||||
return rt;
|
||||
}
|
||||
// return rt;
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,24 +9,24 @@ namespace Esiur.Resource.Template;
|
||||
public class MemberTemplate
|
||||
{
|
||||
|
||||
public readonly byte Index;
|
||||
public readonly string Name;
|
||||
public readonly bool Inherited;
|
||||
public readonly TypeTemplate Template;
|
||||
public byte Index { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool Inherited { get; set; }
|
||||
public TypeTemplate Template { get; set; }
|
||||
|
||||
public MemberTemplate(TypeTemplate template, byte index, string name, bool inherited)
|
||||
{
|
||||
Template = template;
|
||||
Index = index;
|
||||
Name = name;
|
||||
Inherited = inherited;
|
||||
}
|
||||
//public MemberTemplate()
|
||||
//{
|
||||
// Template = template;
|
||||
// Index = index;
|
||||
// Name = name;
|
||||
// Inherited = inherited;
|
||||
//}
|
||||
|
||||
public string Fullname => Template.ClassName + "." + Name;
|
||||
|
||||
public virtual byte[] Compose()
|
||||
{
|
||||
return DC.ToBytes(Name);
|
||||
}
|
||||
//public virtual byte[] Compose()
|
||||
//{
|
||||
// return DC.ToBytes(Name);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,11 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Esiur.Resource.Template;
|
||||
|
||||
public class PropertyTemplate : MemberTemplate
|
||||
{
|
||||
public Map<string, string> Annotations { get; set; }
|
||||
|
||||
public enum PropertyPermission : byte
|
||||
{
|
||||
Read = 1,
|
||||
@@ -42,7 +45,7 @@ public class PropertyTemplate : MemberTemplate
|
||||
set;
|
||||
}
|
||||
|
||||
public bool IsNullable { get; set; }
|
||||
//public bool IsNullable { get; set; }
|
||||
|
||||
public bool Recordable
|
||||
{
|
||||
@@ -57,17 +60,17 @@ public class PropertyTemplate : MemberTemplate
|
||||
set;
|
||||
}*/
|
||||
|
||||
public string ReadAnnotation
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
//public string ReadAnnotation
|
||||
//{
|
||||
// get;
|
||||
// set;
|
||||
//}
|
||||
|
||||
public string WriteAnnotation
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
//public string WriteAnnotation
|
||||
//{
|
||||
// get;
|
||||
// set;
|
||||
//}
|
||||
|
||||
/*
|
||||
public bool Storable
|
||||
@@ -81,50 +84,105 @@ public class PropertyTemplate : MemberTemplate
|
||||
return $"{Name}: {ValueType}";
|
||||
}
|
||||
|
||||
public override byte[] Compose()
|
||||
public static (uint, PropertyTemplate) Parse(byte[] data, uint offset, byte index, bool inherited)
|
||||
{
|
||||
var name = base.Compose();
|
||||
var oOffset = offset;
|
||||
|
||||
|
||||
|
||||
var hasAnnotation = ((data[offset] & 0x8) == 0x8);
|
||||
var recordable = ((data[offset] & 1) == 1);
|
||||
var permission = (PropertyTemplate.PropertyPermission)((data[offset++] >> 1) & 0x3);
|
||||
var name = data.GetString(offset + 1, data[offset]);
|
||||
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
var (dts, valueType) = TRU.Parse(data, offset);
|
||||
|
||||
offset += dts;
|
||||
|
||||
Map<string, string> annotations = null;
|
||||
|
||||
// arguments
|
||||
if (hasAnnotation) // Annotation ?
|
||||
{
|
||||
var (len, anns) = Codec.ParseSync(data, offset, null);
|
||||
|
||||
if (anns is Map<string, string> map)
|
||||
annotations = map;
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return (offset - oOffset, new PropertyTemplate()
|
||||
{
|
||||
Index = index,
|
||||
Name = name,
|
||||
Inherited = inherited,
|
||||
Permission = permission,
|
||||
Recordable = recordable,
|
||||
ValueType = valueType,
|
||||
Annotations = annotations
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public byte[] Compose()
|
||||
{
|
||||
var name = DC.ToBytes(Name);
|
||||
|
||||
var pv = ((byte)(Permission) << 1) | (Recordable ? 1 : 0);
|
||||
|
||||
if (Inherited)
|
||||
pv |= 0x80;
|
||||
|
||||
if (WriteAnnotation != null && ReadAnnotation != null)
|
||||
//if (WriteAnnotation != null && ReadAnnotation != null)
|
||||
//{
|
||||
// var rexp = DC.ToBytes(ReadAnnotation);
|
||||
// var wexp = DC.ToBytes(WriteAnnotation);
|
||||
// return new BinaryList()
|
||||
// .AddUInt8((byte)(0x38 | pv))
|
||||
// .AddUInt8((byte)name.Length)
|
||||
// .AddUInt8Array(name)
|
||||
// .AddUInt8Array(ValueType.Compose())
|
||||
// .AddInt32(wexp.Length)
|
||||
// .AddUInt8Array(wexp)
|
||||
// .AddInt32(rexp.Length)
|
||||
// .AddUInt8Array(rexp)
|
||||
// .ToArray();
|
||||
//}
|
||||
//else if (WriteAnnotation != null)
|
||||
//{
|
||||
// var wexp = DC.ToBytes(WriteAnnotation);
|
||||
// return new BinaryList()
|
||||
// .AddUInt8((byte)(0x30 | pv))
|
||||
// .AddUInt8((byte)name.Length)
|
||||
// .AddUInt8Array(name)
|
||||
// .AddUInt8Array(ValueType.Compose())
|
||||
// .AddInt32(wexp.Length)
|
||||
// .AddUInt8Array(wexp)
|
||||
// .ToArray();
|
||||
//}
|
||||
//else if (ReadAnnotation != null)
|
||||
//{
|
||||
// var rexp = DC.ToBytes(ReadAnnotation);
|
||||
// return new BinaryList()
|
||||
// .AddUInt8((byte)(0x28 | pv))
|
||||
// .AddUInt8((byte)name.Length)
|
||||
// .AddUInt8Array(name)
|
||||
// .AddUInt8Array(ValueType.Compose())
|
||||
// .AddInt32(rexp.Length)
|
||||
// .AddUInt8Array(rexp)
|
||||
// .ToArray();
|
||||
//}
|
||||
if (Annotations != null)
|
||||
{
|
||||
var rexp = DC.ToBytes(ReadAnnotation);
|
||||
var wexp = DC.ToBytes(WriteAnnotation);
|
||||
return new BinaryList()
|
||||
.AddUInt8((byte)(0x38 | pv))
|
||||
.AddUInt8((byte)name.Length)
|
||||
.AddUInt8Array(name)
|
||||
.AddUInt8Array(ValueType.Compose())
|
||||
.AddInt32(wexp.Length)
|
||||
.AddUInt8Array(wexp)
|
||||
.AddInt32(rexp.Length)
|
||||
.AddUInt8Array(rexp)
|
||||
.ToArray();
|
||||
}
|
||||
else if (WriteAnnotation != null)
|
||||
{
|
||||
var wexp = DC.ToBytes(WriteAnnotation);
|
||||
return new BinaryList()
|
||||
.AddUInt8((byte)(0x30 | pv))
|
||||
.AddUInt8((byte)name.Length)
|
||||
.AddUInt8Array(name)
|
||||
.AddUInt8Array(ValueType.Compose())
|
||||
.AddInt32(wexp.Length)
|
||||
.AddUInt8Array(wexp)
|
||||
.ToArray();
|
||||
}
|
||||
else if (ReadAnnotation != null)
|
||||
{
|
||||
var rexp = DC.ToBytes(ReadAnnotation);
|
||||
var rexp = Codec.Compose(Annotations, null, null);
|
||||
return new BinaryList()
|
||||
.AddUInt8((byte)(0x28 | pv))
|
||||
.AddUInt8((byte)name.Length)
|
||||
.AddUInt8Array(name)
|
||||
.AddUInt8Array(ValueType.Compose())
|
||||
.AddInt32(rexp.Length)
|
||||
.AddUInt8Array(rexp)
|
||||
.ToArray();
|
||||
}
|
||||
@@ -139,17 +197,17 @@ public class PropertyTemplate : MemberTemplate
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited,
|
||||
TRU valueType, string readAnnotation = null, string writeAnnotation = null, bool recordable = false)
|
||||
: base(template, index, name, inherited)
|
||||
{
|
||||
this.Recordable = recordable;
|
||||
//this.Storage = storage;
|
||||
if (readAnnotation != null)
|
||||
this.ReadAnnotation = readAnnotation;
|
||||
this.WriteAnnotation = writeAnnotation;
|
||||
this.ValueType = valueType;
|
||||
}
|
||||
//public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited,
|
||||
// TRU valueType, string readAnnotation = null, string writeAnnotation = null, bool recordable = false)
|
||||
// : base(template, index, name, inherited)
|
||||
//{
|
||||
// this.Recordable = recordable;
|
||||
// //this.Storage = storage;
|
||||
// if (readAnnotation != null)
|
||||
// this.ReadAnnotation = readAnnotation;
|
||||
// this.WriteAnnotation = writeAnnotation;
|
||||
// this.ValueType = valueType;
|
||||
//}
|
||||
|
||||
public static PropertyTemplate MakePropertyTemplate(Type type, PropertyInfo pi, byte index = 0, string customName = null, TypeTemplate typeTemplate = null)
|
||||
{
|
||||
@@ -162,7 +220,7 @@ public class PropertyTemplate : MemberTemplate
|
||||
if (propType == null)
|
||||
throw new Exception($"Unsupported type `{pi.PropertyType}` in property `{type.Name}.{pi.Name}`");
|
||||
|
||||
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
|
||||
var annotationAttrs = pi.GetCustomAttributes<AnnotationAttribute>(true);
|
||||
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
|
||||
|
||||
//var nullabilityContext = new NullabilityInfoContext();
|
||||
@@ -196,19 +254,46 @@ public class PropertyTemplate : MemberTemplate
|
||||
propType.SetNull(nullableAttrFlags);
|
||||
}
|
||||
|
||||
var pt = new PropertyTemplate(typeTemplate, index, customName ?? pi.Name, pi.DeclaringType != type, propType);
|
||||
|
||||
if (storageAttr != null)
|
||||
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
||||
Map<string, string> annotations = null;
|
||||
|
||||
if (annotationAttr != null)
|
||||
pt.ReadAnnotation = annotationAttr.Annotation;
|
||||
if (annotationAttrs != null && annotationAttrs.Count() > 0)
|
||||
{
|
||||
annotations = new Map<string, string>();
|
||||
foreach (var attr in annotationAttrs)
|
||||
annotations.Add(attr.Key, attr.Value);
|
||||
}
|
||||
else
|
||||
pt.ReadAnnotation = GetTypeAnnotationName(pi.PropertyType);
|
||||
{
|
||||
annotations = new Map<string, string>();
|
||||
annotations.Add("", GetTypeAnnotationName(pi.PropertyType));
|
||||
}
|
||||
|
||||
pt.PropertyInfo = pi;
|
||||
return new PropertyTemplate()
|
||||
{
|
||||
Name = customName ?? pi.Name,
|
||||
Index = index,
|
||||
Inherited = pi.DeclaringType != type,
|
||||
ValueType = propType,
|
||||
PropertyInfo = pi,
|
||||
Recordable = storageAttr == null ? false : storageAttr.Mode == StorageMode.Recordable,
|
||||
Permission = (pi.CanWrite && pi.CanRead) ? PropertyPermission.ReadWrite : (pi.CanWrite ? PropertyPermission.Write : PropertyPermission.Read),
|
||||
Annotations = annotations,
|
||||
};
|
||||
|
||||
return pt;
|
||||
//var pt = new PropertyTemplate(typeTemplate, index, customName ?? pi.Name, pi.DeclaringType != type, propType);
|
||||
|
||||
//if (storageAttr != null)
|
||||
// pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
||||
|
||||
//if (annotationAttr != null)
|
||||
// pt.ReadAnnotation = annotationAttr.Annotation;
|
||||
//else
|
||||
// pt.ReadAnnotation = GetTypeAnnotationName(pi.PropertyType);
|
||||
|
||||
//pt.PropertyInfo = pi;
|
||||
|
||||
//return pt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,5 +7,6 @@ public enum TemplateType : byte
|
||||
{
|
||||
Resource,
|
||||
Record,
|
||||
Enum
|
||||
Enum,
|
||||
Function
|
||||
}
|
||||
|
||||
@@ -25,10 +25,9 @@ public class TypeTemplate
|
||||
protected UUID classId;
|
||||
protected UUID? parentId;
|
||||
|
||||
public string Annotation { get; set; }
|
||||
public Map<string, string> Annotations { get; set; }
|
||||
|
||||
string className;
|
||||
List<MemberTemplate> members = new List<MemberTemplate>();
|
||||
List<FunctionTemplate> functions = new List<FunctionTemplate>();
|
||||
List<EventTemplate> events = new List<EventTemplate>();
|
||||
List<PropertyTemplate> properties = new List<PropertyTemplate>();
|
||||
@@ -137,10 +136,10 @@ public class TypeTemplate
|
||||
get { return className; }
|
||||
}
|
||||
|
||||
public MemberTemplate[] Methods
|
||||
{
|
||||
get { return members.ToArray(); }
|
||||
}
|
||||
//public MemberTemplate[] Methods
|
||||
//{
|
||||
// get { return members.ToArray(); }
|
||||
//}
|
||||
|
||||
public FunctionTemplate[] Functions
|
||||
{
|
||||
@@ -383,34 +382,12 @@ public class TypeTemplate
|
||||
|
||||
|
||||
|
||||
public static ConstantTemplate MakeConstantTemplate(Type type, FieldInfo ci, ExportAttribute exportAttr, byte index = 0, TypeTemplate typeTemplate = null)
|
||||
{
|
||||
var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true);
|
||||
|
||||
var valueType = TRU.FromType(ci.FieldType);
|
||||
|
||||
if (valueType == null)
|
||||
throw new Exception($"Unsupported type `{ci.FieldType}` in constant `{type.Name}.{ci.Name}`");
|
||||
|
||||
var value = ci.GetValue(null);
|
||||
|
||||
if (typeTemplate.Type == TemplateType.Enum)
|
||||
value = Convert.ChangeType(value, ci.FieldType.GetEnumUnderlyingType());
|
||||
|
||||
var ct = new ConstantTemplate(typeTemplate, index, exportAttr?.Name ?? ci.Name, ci.DeclaringType != type, valueType, value, annotationAttr?.Annotation);
|
||||
|
||||
return ct;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public bool IsWrapper { get; private set; }
|
||||
|
||||
public TypeTemplate(Type type, Warehouse warehouse = null)
|
||||
{
|
||||
|
||||
//if (!type.IsPublic)
|
||||
// throw new Exception("Not public");
|
||||
|
||||
if (Codec.ImplementsInterface(type, typeof(IResource)))
|
||||
templateType = TemplateType.Resource;
|
||||
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
||||
@@ -422,12 +399,6 @@ public class TypeTemplate
|
||||
|
||||
IsWrapper = Codec.InheritsClass(type, typeof(DistributedResource));
|
||||
|
||||
//if (isRecord && isResource)
|
||||
// throw new Exception("Type can't have both IResource and IRecord interfaces");
|
||||
|
||||
//if (!(isResource || isRecord))
|
||||
// throw new Exception("Type is neither a resource nor a record.");
|
||||
|
||||
type = ResourceProxy.GetBaseType(type);
|
||||
|
||||
DefinedType = type;
|
||||
@@ -440,17 +411,6 @@ public class TypeTemplate
|
||||
if (warehouse != null)
|
||||
warehouse.PutTemplate(this);
|
||||
|
||||
|
||||
|
||||
//PropertyInfo[] propsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
//EventInfo[] eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.Instance);
|
||||
//MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
|
||||
//FieldInfo[] constantsInfo = type.GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||
|
||||
|
||||
//bool classIsPublic = type.IsEnum || (type.GetCustomAttribute<PublicAttribute>() != null);
|
||||
|
||||
|
||||
var hierarchy = GetHierarchy(type);
|
||||
|
||||
if (hierarchy.ContainsKey(MemberTypes.Field))
|
||||
@@ -505,19 +465,6 @@ public class TypeTemplate
|
||||
.MakeAttributeTemplate(type, attr, 0, attrAttr?.Name ?? attr.Name, this));
|
||||
}
|
||||
|
||||
// append signals)
|
||||
for (var i = 0; i < events.Count; i++)
|
||||
members.Add(events[i]);
|
||||
// append slots
|
||||
for (var i = 0; i < functions.Count; i++)
|
||||
members.Add(functions[i]);
|
||||
// append properties
|
||||
for (var i = 0; i < properties.Count; i++)
|
||||
members.Add(properties[i]);
|
||||
|
||||
// append constants
|
||||
for (var i = 0; i < constants.Count; i++)
|
||||
members.Add(constants[i]);
|
||||
|
||||
// bake it binarily
|
||||
var b = new BinaryList();
|
||||
@@ -526,8 +473,10 @@ public class TypeTemplate
|
||||
|
||||
|
||||
var hasParent = HasParent(type);
|
||||
var classAnnotation = type.GetCustomAttribute<AnnotationAttribute>(false);
|
||||
var hasClassAnnotation = classAnnotation != null && classAnnotation.Annotation != null;
|
||||
var classAnnotations = type.GetCustomAttributes<AnnotationAttribute>(false);
|
||||
|
||||
|
||||
var hasClassAnnotation = (classAnnotations != null) && (classAnnotations.Count() > 0);
|
||||
|
||||
var classNameBytes = DC.ToBytes(className);
|
||||
|
||||
@@ -546,15 +495,19 @@ public class TypeTemplate
|
||||
|
||||
if (hasClassAnnotation)
|
||||
{
|
||||
var classAnnotationBytes = DC.ToBytes(classAnnotation.Annotation);
|
||||
b.AddUInt16((ushort)classAnnotationBytes.Length)
|
||||
.AddUInt8Array(classAnnotationBytes);
|
||||
Annotations = new Map<string, string>();
|
||||
|
||||
foreach (var ann in classAnnotations)
|
||||
Annotations.Add(ann.Key, ann.Value);
|
||||
|
||||
var classAnnotationBytes = Codec.Compose (Annotations, null, null);
|
||||
|
||||
b.AddUInt8Array(classAnnotationBytes);
|
||||
|
||||
Annotation = classAnnotation.Annotation;
|
||||
}
|
||||
|
||||
b.AddInt32(version)
|
||||
.AddUInt16((ushort)members.Count);
|
||||
.AddUInt16((ushort)(functions.Count + properties.Count + events.Count + constants.Count));
|
||||
|
||||
foreach (var ft in functions)
|
||||
b.AddUInt8Array(ft.Compose());
|
||||
@@ -758,9 +711,11 @@ public class TypeTemplate
|
||||
|
||||
if (hasClassAnnotation)
|
||||
{
|
||||
var len = data.GetUInt16(offset, Endian.Little);
|
||||
offset += 2;
|
||||
od.Annotation = data.GetString(offset, len);
|
||||
var (len, anns) = Codec.ParseSync(data, offset, null);
|
||||
|
||||
if (anns is Map<string, string> annotations)
|
||||
od.Annotations = annotations;
|
||||
|
||||
offset += len;
|
||||
}
|
||||
|
||||
@@ -781,151 +736,32 @@ public class TypeTemplate
|
||||
|
||||
if (type == 0) // function
|
||||
{
|
||||
string annotation = null;
|
||||
var isStatic = ((data[offset] & 0x4) == 0x4);
|
||||
|
||||
|
||||
var hasAnnotation = ((data[offset++] & 0x10) == 0x10);
|
||||
|
||||
var name = data.GetString(offset + 1, data[offset]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
// return type
|
||||
var (rts, returnType) = TRU.Parse(data, offset);
|
||||
offset += rts;
|
||||
|
||||
// arguments count
|
||||
var argsCount = data[offset++];
|
||||
List<ArgumentTemplate> arguments = new();
|
||||
|
||||
for (var a = 0; a < argsCount; a++)
|
||||
{
|
||||
var (cs, argType) = ArgumentTemplate.Parse(data, offset, a);
|
||||
arguments.Add(argType);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
// arguments
|
||||
if (hasAnnotation) // Annotation ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset, Endian.Little);
|
||||
offset += 4;
|
||||
annotation = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var ft = new FunctionTemplate(od, functionIndex++, name, inherited, isStatic, arguments.ToArray(), returnType, annotation);
|
||||
|
||||
var (len, ft) = FunctionTemplate.Parse(data, offset, functionIndex++, inherited);
|
||||
offset += len;
|
||||
od.functions.Add(ft);
|
||||
}
|
||||
else if (type == 1) // property
|
||||
{
|
||||
|
||||
string readAnnotation = null, writeAnnotation = null;
|
||||
|
||||
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]);
|
||||
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
var (dts, valueType) = TRU.Parse(data, offset);
|
||||
|
||||
offset += dts;
|
||||
|
||||
if (hasReadAnnotation) // annotation ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset, Endian.Little);
|
||||
offset += 4;
|
||||
readAnnotation = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
if (hasWriteAnnotation) // annotation ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset, Endian.Little);
|
||||
offset += 4;
|
||||
writeAnnotation = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var pt = new PropertyTemplate(od, propertyIndex++, name, inherited, valueType, readAnnotation, writeAnnotation, recordable);
|
||||
|
||||
var (len, pt) = PropertyTemplate.Parse(data, offset, propertyIndex++, inherited);
|
||||
offset += len;
|
||||
od.properties.Add(pt);
|
||||
|
||||
}
|
||||
else if (type == 2) // Event
|
||||
{
|
||||
|
||||
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]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
var (dts, argType) = TRU.Parse(data, offset);
|
||||
|
||||
offset += dts;
|
||||
|
||||
if (hasAnnotation) // annotation ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset, Endian.Little);
|
||||
offset += 4;
|
||||
annotation = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var et = new EventTemplate(od, eventIndex++, name, inherited, argType, annotation, listenable);
|
||||
|
||||
var (len, et) = EventTemplate.Parse(data, offset, propertyIndex++, inherited);
|
||||
offset += len;
|
||||
od.events.Add(et);
|
||||
|
||||
}
|
||||
// constant
|
||||
else if (type == 3)
|
||||
{
|
||||
string annotation = null;
|
||||
var hasAnnotation = ((data[offset++] & 0x10) == 0x10);
|
||||
|
||||
var name = data.GetString(offset + 1, data[offset]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
var (dts, valueType) = TRU.Parse(data, offset);
|
||||
|
||||
offset += dts;
|
||||
|
||||
(dts, var value) = Codec.ParseSync(data, offset, Warehouse.Default);
|
||||
|
||||
offset += dts;
|
||||
|
||||
if (hasAnnotation) // annotation ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset, Endian.Little);
|
||||
offset += 4;
|
||||
annotation = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var ct = new ConstantTemplate(od, eventIndex++, name, inherited, valueType, value, annotation);
|
||||
|
||||
var (len, ct) = ConstantTemplate.Parse(data, offset, propertyIndex++, inherited);
|
||||
offset += len;
|
||||
od.constants.Add(ct);
|
||||
}
|
||||
}
|
||||
|
||||
// append signals
|
||||
for (int i = 0; i < od.events.Count; i++)
|
||||
od.members.Add(od.events[i]);
|
||||
// append slots
|
||||
for (int i = 0; i < od.functions.Count; i++)
|
||||
od.members.Add(od.functions[i]);
|
||||
// append properties
|
||||
for (int i = 0; i < od.properties.Count; i++)
|
||||
od.members.Add(od.properties[i]);
|
||||
// append constants
|
||||
for (int i = 0; i < od.constants.Count; i++)
|
||||
od.members.Add(od.constants[i]);
|
||||
|
||||
return od;
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +425,7 @@ public class Warehouse
|
||||
/// <param name="resource">Resource instance.</param>
|
||||
/// <param name="store">IStore that manages the resource. Can be null if the resource is a store.</param>
|
||||
/// <param name="parent">Parent resource. if not presented the store becomes the parent for the resource.</param>
|
||||
public async AsyncReply<T> Put<T>(string path, T resource, TypeTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T : IResource
|
||||
public async AsyncReply<T> Put<T>(string path, T resource, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T : IResource
|
||||
{
|
||||
if (resource.Instance != null)
|
||||
throw new Exception("Resource already initialized.");
|
||||
@@ -464,7 +464,7 @@ public class Warehouse
|
||||
|
||||
var resourceReference = new WeakReference<IResource>(resource);
|
||||
|
||||
resource.Instance = new Instance(this, resourceCounter++, instanceName, resource, store, customTemplate, age);
|
||||
resource.Instance = new Instance(this, resourceCounter++, instanceName, resource, store, age);
|
||||
|
||||
if (attributes != null)
|
||||
if (attributes is Map<string, object> attrs)
|
||||
@@ -574,7 +574,7 @@ public class Warehouse
|
||||
public async AsyncReply<IResource> New(Type type, string path, IPermissionsManager manager = null, object attributes = null, object properties = null)
|
||||
{
|
||||
var res = Create(type, properties);
|
||||
return await Put(path, res, null, 0, manager, attributes);
|
||||
return await Put(path, res, 0, manager, attributes);
|
||||
}
|
||||
|
||||
public async AsyncReply<T> New<T>(string path, IPermissionsManager manager = null, object attributes = null, object properties = null)
|
||||
|
||||
Reference in New Issue
Block a user