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:
@@ -1586,7 +1586,7 @@ public static class DataDeserializer
|
|||||||
var pvs = new List<PropertyValue>();
|
var pvs = new List<PropertyValue>();
|
||||||
|
|
||||||
for (var i = 0; i < ar.Length; i += 3)
|
for (var i = 0; i < ar.Length; i += 3)
|
||||||
pvs.Add(new PropertyValue(ar[2], Convert.ToUInt64(ar[0]), (DateTime?)ar[1]));
|
pvs.Add(new PropertyValue(ar[i + 2], Convert.ToUInt64(ar[i]), (DateTime?)ar[i+1]));
|
||||||
|
|
||||||
|
|
||||||
rt.Trigger(pvs.ToArray());
|
rt.Trigger(pvs.ToArray());
|
||||||
|
|||||||
20
Esiur/Data/IDynamicResource.cs
Normal file
20
Esiur/Data/IDynamicResource.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Esiur.Core;
|
||||||
|
using Esiur.Resource.Template;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Data
|
||||||
|
{
|
||||||
|
public interface IDynamicResource
|
||||||
|
{
|
||||||
|
public PropertyValue[] SerializeResource();
|
||||||
|
public Map<byte, PropertyValue> SerializeResourceAfter(ulong age);
|
||||||
|
|
||||||
|
public object GetResourceProperty(byte index);
|
||||||
|
public AsyncReply SetResourcePropertyAsync(byte index, object value);
|
||||||
|
public void SetResourceProperty(byte index, object value);
|
||||||
|
|
||||||
|
public TypeTemplate ResourceTemplate { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,7 +68,7 @@ partial class DistributedConnection
|
|||||||
|
|
||||||
object subscriptionsLock = new object();
|
object subscriptionsLock = new object();
|
||||||
|
|
||||||
AsyncQueue<DistributedResourceQueueItem> queue = new ();
|
AsyncQueue<DistributedResourceQueueItem> queue = new();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -450,7 +450,7 @@ partial class DistributedConnection
|
|||||||
var (valueOffset, valueSize, args) =
|
var (valueOffset, valueSize, args) =
|
||||||
DataDeserializer.LimitedCountListParser(dataType.Data, dataType.Offset, dataType.ContentLength, Instance.Warehouse, 2);
|
DataDeserializer.LimitedCountListParser(dataType.Data, dataType.Offset, dataType.ContentLength, Instance.Warehouse, 2);
|
||||||
|
|
||||||
var rid =Convert.ToUInt32(args[0]);
|
var rid = Convert.ToUInt32(args[0]);
|
||||||
var index = (byte)args[1];
|
var index = (byte)args[1];
|
||||||
|
|
||||||
Fetch(rid, null).Then(r =>
|
Fetch(rid, null).Then(r =>
|
||||||
@@ -559,18 +559,6 @@ partial class DistributedConnection
|
|||||||
// unsubscribe
|
// unsubscribe
|
||||||
Unsubscribe(r);
|
Unsubscribe(r);
|
||||||
|
|
||||||
if (r is DistributedResource dr)
|
|
||||||
{
|
|
||||||
// reply ok
|
|
||||||
SendReply(IIPPacketReply.Completed, callback,
|
|
||||||
r.Instance.Template.ClassId,
|
|
||||||
r.Instance.Age,
|
|
||||||
r.Instance.Link,
|
|
||||||
r.Instance.Hops,
|
|
||||||
dr._Serialize());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reply ok
|
// reply ok
|
||||||
SendReply(IIPPacketReply.Completed, callback,
|
SendReply(IIPPacketReply.Completed, callback,
|
||||||
r.Instance.Template.ClassId,
|
r.Instance.Template.ClassId,
|
||||||
@@ -578,7 +566,6 @@ partial class DistributedConnection
|
|||||||
r.Instance.Link,
|
r.Instance.Link,
|
||||||
r.Instance.Hops,
|
r.Instance.Hops,
|
||||||
r.Instance.Serialize());
|
r.Instance.Serialize());
|
||||||
}
|
|
||||||
|
|
||||||
// subscribe
|
// subscribe
|
||||||
Subscribe(r);
|
Subscribe(r);
|
||||||
@@ -618,18 +605,7 @@ partial class DistributedConnection
|
|||||||
// unsubscribe
|
// unsubscribe
|
||||||
Unsubscribe(r);
|
Unsubscribe(r);
|
||||||
|
|
||||||
if (r is DistributedResource dr)
|
|
||||||
{
|
|
||||||
// reply ok
|
|
||||||
SendReply(IIPPacketReply.Completed, callback,
|
|
||||||
r.Instance.Template.ClassId,
|
|
||||||
r.Instance.Age,
|
|
||||||
r.Instance.Link,
|
|
||||||
r.Instance.Hops,
|
|
||||||
dr._SerializeAfter(age));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reply ok
|
// reply ok
|
||||||
SendReply(IIPPacketReply.Completed, callback,
|
SendReply(IIPPacketReply.Completed, callback,
|
||||||
r.Instance.Template.ClassId,
|
r.Instance.Template.ClassId,
|
||||||
@@ -637,7 +613,7 @@ partial class DistributedConnection
|
|||||||
r.Instance.Link,
|
r.Instance.Link,
|
||||||
r.Instance.Hops,
|
r.Instance.Hops,
|
||||||
r.Instance.SerializeAfter(age));
|
r.Instance.SerializeAfter(age));
|
||||||
}
|
|
||||||
|
|
||||||
// subscribe
|
// subscribe
|
||||||
Subscribe(r);
|
Subscribe(r);
|
||||||
@@ -1612,7 +1588,7 @@ partial class DistributedConnection
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (r is DistributedResource)
|
if (r is IDynamicResource)
|
||||||
{
|
{
|
||||||
var (_, parsed) = Codec.ParseAsync(data, offset, this, null);
|
var (_, parsed) = Codec.ParseAsync(data, offset, this, null);
|
||||||
if (parsed is AsyncReply)
|
if (parsed is AsyncReply)
|
||||||
@@ -1620,7 +1596,7 @@ partial class DistributedConnection
|
|||||||
(parsed as AsyncReply).Then((value) =>
|
(parsed as AsyncReply).Then((value) =>
|
||||||
{
|
{
|
||||||
// propagation
|
// propagation
|
||||||
(r as DistributedResource)._Set(index, value).Then((x) =>
|
(r as IDynamicResource).SetResourcePropertyAsync(index, value).Then((x) =>
|
||||||
{
|
{
|
||||||
SendReply(IIPPacketReply.Completed, callback);
|
SendReply(IIPPacketReply.Completed, callback);
|
||||||
}).Error(x =>
|
}).Error(x =>
|
||||||
@@ -1912,7 +1888,7 @@ partial class DistributedConnection
|
|||||||
{
|
{
|
||||||
template = Instance.Warehouse.GetTemplateByClassId(classId, TemplateType.Resource);
|
template = Instance.Warehouse.GetTemplateByClassId(classId, TemplateType.Resource);
|
||||||
if (template?.DefinedType != null && template.IsWrapper)
|
if (template?.DefinedType != null && template.IsWrapper)
|
||||||
dr = Activator.CreateInstance(template.DefinedType, this, id,Convert.ToUInt64( args[1]), (string)args[2]) as DistributedResource;
|
dr = Activator.CreateInstance(template.DefinedType, this, id, Convert.ToUInt64(args[1]), (string)args[2]) as DistributedResource;
|
||||||
else
|
else
|
||||||
dr = new DistributedResource(this, id, Convert.ToUInt64(args[1]), (string)args[2]);
|
dr = new DistributedResource(this, id, Convert.ToUInt64(args[1]), (string)args[2]);
|
||||||
}
|
}
|
||||||
@@ -1955,7 +1931,9 @@ partial class DistributedConnection
|
|||||||
// ClassId, ResourceAge, ResourceLink, Content
|
// ClassId, ResourceAge, ResourceLink, Content
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr, tmp)
|
dr.ResourceTemplate = tmp;
|
||||||
|
|
||||||
|
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr)
|
||||||
.Then(initResource)
|
.Then(initResource)
|
||||||
.Error(ex => reply.TriggerError(ex));
|
.Error(ex => reply.TriggerError(ex));
|
||||||
}
|
}
|
||||||
@@ -1973,7 +1951,7 @@ partial class DistributedConnection
|
|||||||
{
|
{
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr, template)
|
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr)
|
||||||
.Then(initResource).Error((ex) => reply.TriggerError(ex));
|
.Then(initResource).Error((ex) => reply.TriggerError(ex));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ using Esiur.Net.Packets;
|
|||||||
namespace Esiur.Net.IIP;
|
namespace Esiur.Net.IIP;
|
||||||
|
|
||||||
//[System.Runtime.InteropServices.ComVisible(true)]
|
//[System.Runtime.InteropServices.ComVisible(true)]
|
||||||
public class DistributedResource : DynamicObject, IResource, INotifyPropertyChanged
|
public class DistributedResource : DynamicObject, IResource, INotifyPropertyChanged, IDynamicResource
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -57,6 +57,7 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
uint instanceId;
|
uint instanceId;
|
||||||
|
TypeTemplate template;
|
||||||
DistributedConnection connection;
|
DistributedConnection connection;
|
||||||
|
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
//Structure properties = new Structure();
|
//Structure properties = new Structure();
|
||||||
|
|
||||||
string link;
|
string link;
|
||||||
//ulong age;
|
ulong age;
|
||||||
|
|
||||||
protected object[] properties;
|
protected object[] properties;
|
||||||
internal List<DistributedResource> parents = new List<DistributedResource>();
|
internal List<DistributedResource> parents = new List<DistributedResource>();
|
||||||
@@ -77,17 +78,6 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resource template for the remotely located resource.
|
|
||||||
/// </summary>
|
|
||||||
//public ResourceTemplate Template
|
|
||||||
//{
|
|
||||||
// get { return template; }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connection responsible for the distributed resource.
|
/// Connection responsible for the distributed resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -160,45 +150,9 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
this.link = link;
|
this.link = link;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.instanceId = instanceId;
|
this.instanceId = instanceId;
|
||||||
|
this.age = age;
|
||||||
//this.Instance.Template = template;
|
|
||||||
//this.Instance.Age = age;
|
|
||||||
//this.template = template;
|
|
||||||
//this.age = age;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Export properties as byte array.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal PropertyValue[] _Serialize()
|
|
||||||
{
|
|
||||||
var props = new PropertyValue[properties.Length];
|
|
||||||
|
|
||||||
for (byte i = 0; i < properties.Length; i++)
|
|
||||||
props[i] = new PropertyValue(properties[i],
|
|
||||||
Instance.GetAge(i),
|
|
||||||
Instance.GetModificationDate(i));
|
|
||||||
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Map<byte, PropertyValue> _SerializeAfter(ulong age = 0)
|
|
||||||
{
|
|
||||||
var rt = new Map<byte, PropertyValue>();
|
|
||||||
|
|
||||||
for (byte i = 0; i < properties.Length; i++)
|
|
||||||
if (Instance.GetAge(i) > age)
|
|
||||||
rt.Add(i, new PropertyValue(properties[i],
|
|
||||||
Instance.GetAge(i),
|
|
||||||
Instance.GetModificationDate(i)));
|
|
||||||
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal bool _Attach(PropertyValue[] properties)
|
internal bool _Attach(PropertyValue[] properties)
|
||||||
{
|
{
|
||||||
if (attached)
|
if (attached)
|
||||||
@@ -357,17 +311,14 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Get a property value.
|
///// Get a property value.
|
||||||
/// </summary>
|
///// </summary>
|
||||||
/// <param name="index">Zero-based property index.</param>
|
///// <param name="index">Zero-based property index.</param>
|
||||||
/// <returns>Value</returns>
|
///// <returns>Value</returns>
|
||||||
protected internal object _Get(byte index)
|
//protected internal object _Get(byte index)
|
||||||
{
|
//{
|
||||||
if (index >= properties.Length)
|
//}
|
||||||
return null;
|
|
||||||
return properties[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetPropertyValue(byte index, out object value)
|
public bool TryGetPropertyValue(byte index, out object value)
|
||||||
{
|
{
|
||||||
@@ -427,65 +378,19 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
/// <param name="index">Zero-based property index.</param>
|
/// <param name="index">Zero-based property index.</param>
|
||||||
/// <param name="value">Value</param>
|
/// <param name="value">Value</param>
|
||||||
/// <returns>Indicator when the property is set.</returns>
|
/// <returns>Indicator when the property is set.</returns>
|
||||||
protected object _SetSync(byte index, object value)
|
//protected object _SetSync(byte index, object value)
|
||||||
{
|
//{
|
||||||
//Console.WriteLine("Setting..." + index + " " + value);
|
//}
|
||||||
|
|
||||||
if (destroyed)
|
///// <summary>
|
||||||
throw new Exception("Trying to access a destroyed object.");
|
///// Set property value.
|
||||||
|
///// </summary>
|
||||||
if (suspended)
|
///// <param name="index">Zero-based property index.</param>
|
||||||
throw new Exception("Trying to access a suspended object.");
|
///// <param name="value">Value</param>
|
||||||
|
///// <returns>Indicator when the property is set.</returns>
|
||||||
if (!attached)
|
//protected internal AsyncReply<object> _Set(byte index, object value)
|
||||||
return null;
|
//{
|
||||||
|
//}
|
||||||
if (index >= properties.Length)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// Don't set the same current value
|
|
||||||
if (properties[index] == value)
|
|
||||||
return value;
|
|
||||||
|
|
||||||
var rt = _Set(index, value).Wait();
|
|
||||||
|
|
||||||
//Console.WriteLine("Done Setting");
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set property value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">Zero-based property index.</param>
|
|
||||||
/// <param name="value">Value</param>
|
|
||||||
/// <returns>Indicator when the property is set.</returns>
|
|
||||||
protected internal AsyncReply<object> _Set(byte index, object value)
|
|
||||||
{
|
|
||||||
if (destroyed)
|
|
||||||
throw new Exception("Trying to access a destroyed object.");
|
|
||||||
|
|
||||||
if (suspended)
|
|
||||||
throw new Exception("Trying to access a suspended object.");
|
|
||||||
|
|
||||||
if (!attached)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (index >= properties.Length)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var reply = new AsyncReply<object>();
|
|
||||||
|
|
||||||
connection.SendSetProperty(instanceId, index, value)
|
|
||||||
.Then((res) =>
|
|
||||||
{
|
|
||||||
// not really needed, server will always send property modified,
|
|
||||||
// this only happens if the programmer forgot to emit in property setter
|
|
||||||
properties[index] = value;
|
|
||||||
reply.Trigger(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool TrySetMember(SetMemberBinder binder, object value)
|
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||||
{
|
{
|
||||||
@@ -502,7 +407,7 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
|
|
||||||
if (pt != null)
|
if (pt != null)
|
||||||
{
|
{
|
||||||
_Set(pt.Index, value);
|
SetResourceProperty(pt.Index, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -518,33 +423,6 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public async void InvokeMethod(byte index, object[] arguments, DistributedConnection sender)
|
|
||||||
{
|
|
||||||
// get function parameters
|
|
||||||
Type t = this.GetType();
|
|
||||||
|
|
||||||
MethodInfo mi = t.GetMethod(GetFunctionName(index), BindingFlags.DeclaredOnly |
|
|
||||||
BindingFlags.Public |
|
|
||||||
BindingFlags.Instance | BindingFlags.InvokeMethod);
|
|
||||||
if (mi != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var res = await invokeMethod(mi, arguments, sender);
|
|
||||||
object rt = Codec.Compose(res);
|
|
||||||
sender.SendParams((byte)0x80, instanceId, index, rt);
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
var msg = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
|
|
||||||
sender.SendParams((byte)0x8E, instanceId, index, Codec.Compose(msg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resource interface.
|
/// Resource interface.
|
||||||
@@ -555,6 +433,18 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TypeTemplate ResourceTemplate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
template = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance of distributed resource.
|
/// Create a new instance of distributed resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -587,6 +477,82 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan
|
|||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PropertyValue[] SerializeResource()
|
||||||
|
{
|
||||||
|
var props = new PropertyValue[properties.Length];
|
||||||
|
|
||||||
|
for (byte i = 0; i < properties.Length; i++)
|
||||||
|
props[i] = new PropertyValue(properties[i],
|
||||||
|
Instance.GetAge(i),
|
||||||
|
Instance.GetModificationDate(i));
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<byte, PropertyValue> SerializeResourceAfter(ulong age = 0)
|
||||||
|
{
|
||||||
|
var rt = new Map<byte, PropertyValue>();
|
||||||
|
|
||||||
|
for (byte i = 0; i < properties.Length; i++)
|
||||||
|
if (Instance.GetAge(i) > age)
|
||||||
|
rt.Add(i, new PropertyValue(properties[i],
|
||||||
|
Instance.GetAge(i),
|
||||||
|
Instance.GetModificationDate(i)));
|
||||||
|
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public object GetResourceProperty(byte index)
|
||||||
|
{
|
||||||
|
if (index >= properties.Length)
|
||||||
|
return null;
|
||||||
|
return properties[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncReply SetResourcePropertyAsync(byte index, object value)
|
||||||
|
{
|
||||||
|
if (destroyed)
|
||||||
|
throw new Exception("Trying to access a destroyed object.");
|
||||||
|
|
||||||
|
if (suspended)
|
||||||
|
throw new Exception("Trying to access a suspended object.");
|
||||||
|
|
||||||
|
if (!attached)
|
||||||
|
throw new Exception("Resource is not attached.");
|
||||||
|
|
||||||
|
if (index >= properties.Length)
|
||||||
|
throw new Exception("Property index not found."); ;
|
||||||
|
|
||||||
|
var reply = new AsyncReply<object>();
|
||||||
|
|
||||||
|
connection.SendSetProperty(instanceId, index, value)
|
||||||
|
.Then((res) =>
|
||||||
|
{
|
||||||
|
// not really needed, server will always send property modified,
|
||||||
|
// this only happens if the programmer forgot to emit in property setter
|
||||||
|
properties[index] = value;
|
||||||
|
reply.Trigger(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetResourceProperty(byte index, object value)
|
||||||
|
{
|
||||||
|
// Don't set the same current value
|
||||||
|
if (properties[index] == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetResourcePropertyAsync(index, value).Wait();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
~DistributedResource()
|
~DistributedResource()
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|||||||
@@ -74,9 +74,13 @@ 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("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
|
||||||
rt.AppendLine($"namespace {nameSpace} {{");
|
rt.AppendLine($"namespace {nameSpace} {{");
|
||||||
|
|
||||||
if (template.Annotation != null)
|
if (template.Annotations != null)
|
||||||
rt.AppendLine($"[Annotation({ToLiteral(template.Annotation)})]");
|
{
|
||||||
|
foreach (var ann in template.Annotations)
|
||||||
|
{
|
||||||
|
rt.AppendLine($"[Annotation({ToLiteral(ann.Key)}, {ToLiteral(ann.Value)})]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rt.AppendLine($"[ClassId(\"{template.ClassId.Data.ToHex(0, 16, null)}\")]");
|
rt.AppendLine($"[ClassId(\"{template.ClassId.Data.ToHex(0, 16, null)}\")]");
|
||||||
rt.AppendLine($"[Export] public class {className} : IRecord {{");
|
rt.AppendLine($"[Export] public class {className} : IRecord {{");
|
||||||
@@ -85,8 +89,17 @@ public static class TemplateGenerator
|
|||||||
foreach (var p in template.Properties)
|
foreach (var p in template.Properties)
|
||||||
{
|
{
|
||||||
var ptTypeName = GetTypeName(p.ValueType, templates);
|
var ptTypeName = GetTypeName(p.ValueType, templates);
|
||||||
if (p.ReadAnnotation != null)
|
|
||||||
rt.AppendLine($"[Annotation({ToLiteral(p.ReadAnnotation)})]");
|
|
||||||
|
if (p.Annotations != null)
|
||||||
|
{
|
||||||
|
foreach (var ann in p.Annotations)
|
||||||
|
{
|
||||||
|
rt.AppendLine($"[Annotation({ToLiteral(ann.Key)}, {ToLiteral(ann.Value)})]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
rt.AppendLine($"public {ptTypeName} {p.Name} {{ get; set; }}");
|
rt.AppendLine($"public {ptTypeName} {p.Name} {{ get; set; }}");
|
||||||
rt.AppendLine();
|
rt.AppendLine();
|
||||||
}
|
}
|
||||||
@@ -108,8 +121,13 @@ 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("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
|
||||||
rt.AppendLine($"namespace {nameSpace} {{");
|
rt.AppendLine($"namespace {nameSpace} {{");
|
||||||
|
|
||||||
if (template.Annotation != null)
|
if (template.Annotations != null)
|
||||||
rt.AppendLine($"[Annotation({ToLiteral(template.Annotation)})]");
|
{
|
||||||
|
foreach (var ann in template.Annotations)
|
||||||
|
{
|
||||||
|
rt.AppendLine($"[Annotation({ToLiteral(ann.Key)}, {ToLiteral(ann.Value)})]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rt.AppendLine($"[ClassId(\"{template.ClassId.Data.ToHex(0, 16, null)}\")]");
|
rt.AppendLine($"[ClassId(\"{template.ClassId.Data.ToHex(0, 16, null)}\")]");
|
||||||
rt.AppendLine($"[Export] public enum {className} {{");
|
rt.AppendLine($"[Export] public enum {className} {{");
|
||||||
@@ -275,8 +293,13 @@ public static class TemplateGenerator
|
|||||||
|
|
||||||
rt.AppendLine($"namespace {nameSpace} {{");
|
rt.AppendLine($"namespace {nameSpace} {{");
|
||||||
|
|
||||||
if (template.Annotation != null)
|
if (template.Annotations != null)
|
||||||
rt.AppendLine($"[Annotation({ToLiteral(template.Annotation)})]");
|
{
|
||||||
|
foreach (var ann in template.Annotations)
|
||||||
|
{
|
||||||
|
rt.AppendLine($"[Annotation({ToLiteral(ann.Key)}, {ToLiteral(ann.Value)})]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
rt.AppendLine($"[ClassId(\"{template.ClassId.Data.ToHex(0, 16, null)}\")]");
|
rt.AppendLine($"[ClassId(\"{template.ClassId.Data.ToHex(0, 16, null)}\")]");
|
||||||
@@ -371,8 +394,13 @@ public static class TemplateGenerator
|
|||||||
if (p.Inherited)
|
if (p.Inherited)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (p.ReadAnnotation != null)
|
if (p.Annotations != null)
|
||||||
rt.AppendLine($"[Annotation({ToLiteral(p.ReadAnnotation)})]");
|
{
|
||||||
|
foreach (var ann in p.Annotations)
|
||||||
|
{
|
||||||
|
rt.AppendLine($"[Annotation({ToLiteral(ann.Key)}, {ToLiteral(ann.Value)})]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ptTypeName = GetTypeName(p.ValueType, templates);
|
var ptTypeName = GetTypeName(p.ValueType, templates);
|
||||||
rt.AppendLine($"[Export] public {ptTypeName} {p.Name} {{");
|
rt.AppendLine($"[Export] public {ptTypeName} {p.Name} {{");
|
||||||
@@ -389,8 +417,11 @@ public static class TemplateGenerator
|
|||||||
if (c.Inherited)
|
if (c.Inherited)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c.Annotation != null)
|
if (c.Annotations != null)
|
||||||
rt.AppendLine($"[Annotation({ToLiteral(c.Annotation)})]");
|
{
|
||||||
|
foreach (var ann in c.Annotations)
|
||||||
|
rt.AppendLine($"[Annotation({ToLiteral(ann.Key)}, {ToLiteral(ann.Value)})]");
|
||||||
|
}
|
||||||
|
|
||||||
var ctTypeName = GetTypeName(c.ValueType, templates);
|
var ctTypeName = GetTypeName(c.ValueType, templates);
|
||||||
rt.AppendLine($"[Export] public const {ctTypeName} {c.Name} = {c.Value};");
|
rt.AppendLine($"[Export] public const {ctTypeName} {c.Name} = {c.Value};");
|
||||||
@@ -410,8 +441,13 @@ public static class TemplateGenerator
|
|||||||
var etTypeName = GetTypeName(e.ArgumentType, templates);
|
var etTypeName = GetTypeName(e.ArgumentType, templates);
|
||||||
rt.AppendLine($"case {e.Index}: {e.Name}?.Invoke(({etTypeName})args); break;");
|
rt.AppendLine($"case {e.Index}: {e.Name}?.Invoke(({etTypeName})args); break;");
|
||||||
|
|
||||||
if (e.Annotation != null)
|
|
||||||
eventsList.AppendLine($"[Annotation({ToLiteral(e.Annotation)})]");
|
if (e.Annotations != null)
|
||||||
|
{
|
||||||
|
foreach (var ann in e.Annotations)
|
||||||
|
rt.AppendLine($"[Annotation({ToLiteral(ann.Key)}, {ToLiteral(ann.Value)})]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
eventsList.AppendLine($"[Export] public event ResourceEventHandler<{etTypeName}> {e.Name};");
|
eventsList.AppendLine($"[Export] public event ResourceEventHandler<{etTypeName}> {e.Name};");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Text;
|
|||||||
|
|
||||||
namespace Esiur.Resource;
|
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
|
public class AnnotationAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ public class AnnotationAttribute : Attribute
|
|||||||
|
|
||||||
public AnnotationAttribute(string annotation)
|
public AnnotationAttribute(string annotation)
|
||||||
{
|
{
|
||||||
Key = null;
|
Key = "";
|
||||||
Value = annotation;
|
Value = annotation;
|
||||||
}
|
}
|
||||||
public AnnotationAttribute(string key, string value)
|
public AnnotationAttribute(string key, string value)
|
||||||
|
|||||||
@@ -116,58 +116,6 @@ public class Instance
|
|||||||
}
|
}
|
||||||
|
|
||||||
return rt;
|
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)
|
public bool SetAttributes(Map<string, object> attributes, bool clearAttributes = false)
|
||||||
@@ -454,18 +402,22 @@ public class Instance
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public PropertyValue[] Serialize()
|
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>();
|
var props = new List<PropertyValue>();
|
||||||
|
|
||||||
foreach (var pt in template.Properties)
|
foreach (var pt in template.Properties)
|
||||||
{
|
|
||||||
IResource res;
|
|
||||||
|
|
||||||
if (resource.TryGetTarget(out res))
|
|
||||||
{
|
{
|
||||||
var rt = pt.PropertyInfo.GetValue(res, null);
|
var rt = pt.PropertyInfo.GetValue(res, null);
|
||||||
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
|
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return props.ToArray();
|
return props.ToArray();
|
||||||
}
|
}
|
||||||
@@ -476,12 +428,17 @@ public class Instance
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Map<byte, PropertyValue> SerializeAfter(ulong age = 0)
|
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>();
|
var props = new Map<byte, PropertyValue>();
|
||||||
|
|
||||||
foreach (var pt in template.Properties)
|
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)
|
||||||
{
|
{
|
||||||
@@ -492,77 +449,10 @@ public class Instance
|
|||||||
modificationDates[pt.Index]));
|
modificationDates[pt.Index]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return props;
|
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>
|
/// <summary>
|
||||||
/// If True, the instance can be stored to disk.
|
/// If True, the instance can be stored to disk.
|
||||||
@@ -619,7 +509,7 @@ public class Instance
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
object value;
|
object value;
|
||||||
if (GetPropertyValue(propertyName, out value))
|
if (TryGetPropertyValue(propertyName, out value))
|
||||||
{
|
{
|
||||||
var pt = template.GetPropertyTemplateByName(propertyName);
|
var pt = template.GetPropertyTemplateByName(propertyName);
|
||||||
EmitModification(pt, value);
|
EmitModification(pt, value);
|
||||||
@@ -675,66 +565,37 @@ public class Instance
|
|||||||
/// <param name="name">Property name</param>
|
/// <param name="name">Property name</param>
|
||||||
/// <param name="value">Output value</param>
|
/// <param name="value">Output value</param>
|
||||||
/// <returns>True, if the resource has the property.</returns>
|
/// <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);
|
var pt = template.GetPropertyTemplateByName(name);
|
||||||
|
|
||||||
if (pt != null && pt.PropertyInfo != null)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
#if NETSTANDARD
|
|
||||||
object[] ca = pi.GetCustomAttributes(typeof(ResourceProperty), false).ToArray();
|
|
||||||
|
|
||||||
#else
|
|
||||||
object[] ca = pi.GetCustomAttributes(typeof(ResourceProperty), false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ca.Length > 0)
|
|
||||||
{
|
|
||||||
value = pi.GetValue(resource, null);
|
|
||||||
//if (value is Func<IManager, object>)
|
|
||||||
// value = (value as Func<IManager, object>)(sender);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
IResource res;
|
IResource res;
|
||||||
if (resource.TryGetTarget(out res))
|
if (resource.TryGetTarget(out res))
|
||||||
value = pt.PropertyInfo.GetValue(res, null);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
value = null;
|
if (res is IDynamicResource dynamicResource)
|
||||||
return false;
|
{
|
||||||
}
|
value = dynamicResource.GetResourceProperty(pt.Index);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else if (pt != null && pt.PropertyInfo != null)
|
||||||
|
{
|
||||||
|
value = pt.PropertyInfo.GetValue(res, null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value = null;
|
value = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object GetPropertyValueOrDefault(string name, object defaultValue = null)
|
||||||
/*
|
|
||||||
public bool Inherit
|
|
||||||
{
|
{
|
||||||
get { return inherit; }
|
object value;
|
||||||
}*/
|
if (TryGetPropertyValue(name, out value))
|
||||||
|
return value;
|
||||||
/// <summary>
|
else
|
||||||
/// List of parents.
|
return defaultValue;
|
||||||
/// </summary>
|
}
|
||||||
//public AutoList<IResource, Instance> Parents => parents;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Store responsible for creating and keeping the resource.
|
/// Store responsible for creating and keeping the resource.
|
||||||
@@ -746,11 +607,6 @@ public class Instance
|
|||||||
|
|
||||||
public bool IsDestroyed { get; private set; }
|
public bool IsDestroyed { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of children.
|
|
||||||
/// </summary>
|
|
||||||
// public AutoList<IResource, Instance> Children => children;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The unique and permanent link to the resource.
|
/// The unique and permanent link to the resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -793,35 +649,6 @@ public class Instance
|
|||||||
return new AsyncBag<T>(default(T[]));
|
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>
|
/// <summary>
|
||||||
/// Instance name.
|
/// Instance name.
|
||||||
@@ -913,7 +740,7 @@ public class Instance
|
|||||||
/// <param name="name">Name of the instance.</param>
|
/// <param name="name">Name of the instance.</param>
|
||||||
/// <param name="resource">Resource to manage.</param>
|
/// <param name="resource">Resource to manage.</param>
|
||||||
/// <param name="store">Store responsible for the resource.</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.Warehouse = warehouse;
|
||||||
this.store = store;
|
this.store = store;
|
||||||
@@ -933,10 +760,14 @@ public class Instance
|
|||||||
|
|
||||||
resource.OnDestroy += Resource_OnDestroy;
|
resource.OnDestroy += Resource_OnDestroy;
|
||||||
|
|
||||||
if (customTemplate != null)
|
if (resource is IDynamicResource dynamicResource)
|
||||||
this.template = customTemplate;
|
{
|
||||||
|
this.template = dynamicResource.ResourceTemplate;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
this.template = Warehouse.GetTemplateByType(resource.GetType());
|
this.template = Warehouse.GetTemplateByType(resource.GetType());
|
||||||
|
}
|
||||||
|
|
||||||
// set ages
|
// set ages
|
||||||
for (byte i = 0; i < template.Properties.Length; i++)
|
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)
|
private void Resource_OnDestroy(object sender)
|
||||||
{
|
{
|
||||||
IsDestroyed = true;
|
IsDestroyed = true;
|
||||||
|
|||||||
@@ -30,20 +30,30 @@ public class ArgumentTemplate
|
|||||||
offset += cs;
|
offset += cs;
|
||||||
var (size, type) = TRU.Parse(data, offset);
|
var (size, type) = TRU.Parse(data, offset);
|
||||||
|
|
||||||
|
offset += size;
|
||||||
|
|
||||||
Map<string, string> annotations = null;
|
Map<string, string> annotations = null;
|
||||||
|
|
||||||
if (hasAnnotations)
|
if (hasAnnotations)
|
||||||
{
|
{
|
||||||
var acs = data.GetUInt32(offset, Endian.Little);
|
//var acs = data.GetUInt32(offset, Endian.Little);
|
||||||
offset += 2;
|
//offset += 2;
|
||||||
var (l, a) = Codec.ParseSync(data, offset, null);
|
var (l, a) = Codec.ParseSync(data, offset, null);
|
||||||
// for saftey, Map<string, string> might change in the future
|
// for saftey, Map<string, string> might change in the future
|
||||||
if (a is Map<string, string> ann)
|
if (a is Map<string, string> ann)
|
||||||
annotations = 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()
|
public ArgumentTemplate()
|
||||||
@@ -51,14 +61,6 @@ 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()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
@@ -90,10 +92,8 @@ public class ArgumentTemplate
|
|||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
.AddUInt8Array(name)
|
.AddUInt8Array(name)
|
||||||
.AddUInt8Array(Type.Compose())
|
.AddUInt8Array(Type.Compose())
|
||||||
.AddUInt32((ushort)exp.Length)
|
|
||||||
.AddUInt8Array(exp)
|
.AddUInt8Array(exp)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace Esiur.Resource.Template;
|
|||||||
|
|
||||||
public class AttributeTemplate : MemberTemplate
|
public class AttributeTemplate : MemberTemplate
|
||||||
{
|
{
|
||||||
|
|
||||||
public PropertyInfo PropertyInfo
|
public PropertyInfo PropertyInfo
|
||||||
{
|
{
|
||||||
get;
|
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)
|
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);
|
return new AttributeTemplate()
|
||||||
at.PropertyInfo = pi;
|
{
|
||||||
return at;
|
Index = index,
|
||||||
|
Inherited = pi.DeclaringType != type,
|
||||||
|
Name = customName,
|
||||||
|
PropertyInfo = pi
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,33 +9,59 @@ namespace Esiur.Resource.Template;
|
|||||||
|
|
||||||
public class ConstantTemplate : MemberTemplate
|
public class ConstantTemplate : MemberTemplate
|
||||||
{
|
{
|
||||||
public readonly object Value;
|
public object Value { get; set; }
|
||||||
|
|
||||||
public Map<string, string> Annotations;
|
public Map<string, string> Annotations { get; set; }
|
||||||
public readonly TRU ValueType;
|
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;
|
var oOffset = offset;
|
||||||
ValueType = valueType;
|
|
||||||
Value = value;
|
var hasAnnotation = ((data[offset++] & 0x10) == 0x10);
|
||||||
//try
|
|
||||||
//{
|
var name = data.GetString(offset + 1, data[offset]);
|
||||||
// Codec.Compose(value, null);
|
offset += (uint)data[offset] + 1;
|
||||||
// Value = value;
|
|
||||||
//}
|
var (dts, valueType) = TRU.Parse(data, offset);
|
||||||
//catch
|
|
||||||
//{
|
offset += dts;
|
||||||
// throw new Exception($"Constant `{template.ClassName}.{name}` can't be serialized.");
|
|
||||||
//}
|
(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] Compose()
|
return (offset - oOffset, new ConstantTemplate()
|
||||||
{
|
{
|
||||||
var name = base.Compose();
|
Index = index,
|
||||||
|
Name = name,
|
||||||
|
Inherited = inherited,
|
||||||
|
ValueType = valueType,
|
||||||
|
Value = value,
|
||||||
|
Annotations = annotations
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Compose()
|
||||||
|
{
|
||||||
|
var name = DC.ToBytes(Name);
|
||||||
|
|
||||||
var hdr = Inherited ? (byte)0x80 : (byte)0;
|
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 class EventTemplate : MemberTemplate
|
||||||
{
|
{
|
||||||
|
|
||||||
public Map<string, string> Annotations
|
public Map<string, string> Annotations
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -29,9 +30,48 @@ public class EventTemplate : MemberTemplate
|
|||||||
|
|
||||||
public TRU ArgumentType { get; set; }
|
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;
|
var hdr = Inherited ? (byte)0x80 : (byte)0;
|
||||||
|
|
||||||
@@ -62,13 +102,13 @@ public class EventTemplate : MemberTemplate
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU argumentType, Map<string, string> annotations = null, bool subscribable = false)
|
//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)
|
// : base(template, index, name, inherited)
|
||||||
{
|
//{
|
||||||
this.Annotations = annotations;
|
// this.Annotations = annotations;
|
||||||
this.Subscribable = subscribable;
|
// this.Subscribable = subscribable;
|
||||||
this.ArgumentType = argumentType;
|
// this.ArgumentType = argumentType;
|
||||||
}
|
//}
|
||||||
|
|
||||||
public static EventTemplate MakeEventTemplate(Type type, EventInfo ei, byte index = 0, string customName = null, TypeTemplate typeTemplate = null)
|
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);
|
evtType.SetNull(nullableAttrFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
var et = new EventTemplate(typeTemplate, index, customName ?? ei.Name, ei.DeclaringType != type, evtType);
|
Map<string, string> annotations = null;
|
||||||
et.EventInfo = ei;
|
|
||||||
|
|
||||||
|
|
||||||
if (annotationAttrs != null && annotationAttrs.Count() > 0)
|
if (annotationAttrs != null && annotationAttrs.Count() > 0)
|
||||||
{
|
{
|
||||||
et.Annotations = new Map<string, string>();
|
annotations = new Map<string, string>();
|
||||||
foreach (var attr in annotationAttrs)
|
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;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Esiur.Resource.Template;
|
namespace Esiur.Resource.Template;
|
||||||
|
|
||||||
public class FunctionTemplate : MemberTemplate
|
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()
|
var bl = new BinaryList()
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
@@ -56,8 +108,7 @@ public class FunctionTemplate : MemberTemplate
|
|||||||
if (Annotations != null)
|
if (Annotations != null)
|
||||||
{
|
{
|
||||||
var exp = Codec.Compose(Annotations, null, null);// DC.ToBytes(Annotation);
|
var exp = Codec.Compose(Annotations, null, null);// DC.ToBytes(Annotation);
|
||||||
bl.AddInt32(exp.Length)
|
bl.AddUInt8Array(exp);
|
||||||
.AddUInt8Array(exp);
|
|
||||||
bl.InsertUInt8(0, (byte)((Inherited ? (byte)0x90 : (byte)0x10) | (IsStatic ? 0x4 : 0)));
|
bl.InsertUInt8(0, (byte)((Inherited ? (byte)0x90 : (byte)0x10) | (IsStatic ? 0x4 : 0)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -66,14 +117,14 @@ public class FunctionTemplate : MemberTemplate
|
|||||||
return bl.ToArray();
|
return bl.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, bool isStatic, ArgumentTemplate[] arguments, TRU returnType, Map<string, string> annotations = null)
|
//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)
|
// : base(template, index, name, inherited)
|
||||||
{
|
//{
|
||||||
this.Arguments = arguments;
|
// this.Arguments = arguments;
|
||||||
this.ReturnType = returnType;
|
// this.ReturnType = returnType;
|
||||||
this.Annotations = annotations;
|
// this.Annotations = annotations;
|
||||||
this.IsStatic = isStatic;
|
// this.IsStatic = isStatic;
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -99,6 +150,9 @@ public class FunctionTemplate : MemberTemplate
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (mi.ReturnType == typeof(Task))
|
||||||
|
rtType = TRU.FromType(null);
|
||||||
|
else
|
||||||
rtType = TRU.FromType(mi.ReturnType);
|
rtType = TRU.FromType(mi.ReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,32 +273,35 @@ public class FunctionTemplate : MemberTemplate
|
|||||||
})
|
})
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
var fn = customName ?? mi.Name;
|
Map<string, string> annotations = null;
|
||||||
|
|
||||||
var ft = new FunctionTemplate(typeTemplate, index, fn, mi.DeclaringType != type,
|
|
||||||
mi.IsStatic,
|
|
||||||
arguments, rtType);
|
|
||||||
|
|
||||||
|
|
||||||
if (annotationAttrs != null && annotationAttrs.Count() > 0)
|
if (annotationAttrs != null && annotationAttrs.Count() > 0)
|
||||||
{
|
{
|
||||||
ft.Annotations = new Map<string, string>();
|
annotations = new Map<string, string>();
|
||||||
foreach (var attr in annotationAttrs)
|
foreach (var attr in annotationAttrs)
|
||||||
ft.Annotations.Add(attr.Key, attr.Value);
|
annotations.Add(attr.Key, attr.Value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ft.Annotations = new Map<string, string>();
|
annotations = new Map<string, string>();
|
||||||
ft.Annotations.Add(null, "(" + String.Join(",",
|
annotations.Add("", "(" + String.Join(",",
|
||||||
mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection))
|
mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection))
|
||||||
.Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name);
|
.Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ft.MethodInfo = mi;
|
return new FunctionTemplate()
|
||||||
// functions.Add(ft);
|
{
|
||||||
|
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()
|
public override string ToString()
|
||||||
|
|||||||
@@ -40,19 +40,19 @@ public class MemberData
|
|||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetAnnotation()
|
//public string? GetAnnotation()
|
||||||
{
|
//{
|
||||||
string? rt = null;
|
// string? rt = null;
|
||||||
var md = this;
|
// var md = this;
|
||||||
while (md != null)
|
// while (md != null)
|
||||||
{
|
// {
|
||||||
var annotationAttr = md.Info.GetCustomAttribute<AnnotationAttribute>();
|
// var annotationAttr = md.Info.GetCustomAttribute<AnnotationAttribute>();
|
||||||
if (annotationAttr != null)
|
// if (annotationAttr != null)
|
||||||
rt = annotationAttr.Annotation;
|
// rt = annotationAttr.Annotation;
|
||||||
md = md.Child;
|
// md = md.Child;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return rt;
|
// return rt;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,24 +9,24 @@ namespace Esiur.Resource.Template;
|
|||||||
public class MemberTemplate
|
public class MemberTemplate
|
||||||
{
|
{
|
||||||
|
|
||||||
public readonly byte Index;
|
public byte Index { get; set; }
|
||||||
public readonly string Name;
|
public string Name { get; set; }
|
||||||
public readonly bool Inherited;
|
public bool Inherited { get; set; }
|
||||||
public readonly TypeTemplate Template;
|
public TypeTemplate Template { get; set; }
|
||||||
|
|
||||||
public MemberTemplate(TypeTemplate template, byte index, string name, bool inherited)
|
//public MemberTemplate()
|
||||||
{
|
//{
|
||||||
Template = template;
|
// Template = template;
|
||||||
Index = index;
|
// Index = index;
|
||||||
Name = name;
|
// Name = name;
|
||||||
Inherited = inherited;
|
// Inherited = inherited;
|
||||||
}
|
//}
|
||||||
|
|
||||||
public string Fullname => Template.ClassName + "." + Name;
|
public string Fullname => Template.ClassName + "." + Name;
|
||||||
|
|
||||||
public virtual byte[] Compose()
|
//public virtual byte[] Compose()
|
||||||
{
|
//{
|
||||||
return DC.ToBytes(Name);
|
// return DC.ToBytes(Name);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Esiur.Resource.Template;
|
namespace Esiur.Resource.Template;
|
||||||
|
|
||||||
public class PropertyTemplate : MemberTemplate
|
public class PropertyTemplate : MemberTemplate
|
||||||
{
|
{
|
||||||
|
public Map<string, string> Annotations { get; set; }
|
||||||
|
|
||||||
public enum PropertyPermission : byte
|
public enum PropertyPermission : byte
|
||||||
{
|
{
|
||||||
Read = 1,
|
Read = 1,
|
||||||
@@ -42,7 +45,7 @@ public class PropertyTemplate : MemberTemplate
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsNullable { get; set; }
|
//public bool IsNullable { get; set; }
|
||||||
|
|
||||||
public bool Recordable
|
public bool Recordable
|
||||||
{
|
{
|
||||||
@@ -57,17 +60,17 @@ public class PropertyTemplate : MemberTemplate
|
|||||||
set;
|
set;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public string ReadAnnotation
|
//public string ReadAnnotation
|
||||||
{
|
//{
|
||||||
get;
|
// get;
|
||||||
set;
|
// set;
|
||||||
}
|
//}
|
||||||
|
|
||||||
public string WriteAnnotation
|
//public string WriteAnnotation
|
||||||
{
|
//{
|
||||||
get;
|
// get;
|
||||||
set;
|
// set;
|
||||||
}
|
//}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public bool Storable
|
public bool Storable
|
||||||
@@ -81,50 +84,105 @@ public class PropertyTemplate : MemberTemplate
|
|||||||
return $"{Name}: {ValueType}";
|
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);
|
var pv = ((byte)(Permission) << 1) | (Recordable ? 1 : 0);
|
||||||
|
|
||||||
if (Inherited)
|
if (Inherited)
|
||||||
pv |= 0x80;
|
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 rexp = Codec.Compose(Annotations, null, null);
|
||||||
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()
|
return new BinaryList()
|
||||||
.AddUInt8((byte)(0x28 | pv))
|
.AddUInt8((byte)(0x28 | pv))
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
.AddUInt8Array(name)
|
.AddUInt8Array(name)
|
||||||
.AddUInt8Array(ValueType.Compose())
|
.AddUInt8Array(ValueType.Compose())
|
||||||
.AddInt32(rexp.Length)
|
|
||||||
.AddUInt8Array(rexp)
|
.AddUInt8Array(rexp)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
@@ -139,17 +197,17 @@ public class PropertyTemplate : MemberTemplate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited,
|
//public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited,
|
||||||
TRU valueType, string readAnnotation = null, string writeAnnotation = null, bool recordable = false)
|
// TRU valueType, string readAnnotation = null, string writeAnnotation = null, bool recordable = false)
|
||||||
: base(template, index, name, inherited)
|
// : base(template, index, name, inherited)
|
||||||
{
|
//{
|
||||||
this.Recordable = recordable;
|
// this.Recordable = recordable;
|
||||||
//this.Storage = storage;
|
// //this.Storage = storage;
|
||||||
if (readAnnotation != null)
|
// if (readAnnotation != null)
|
||||||
this.ReadAnnotation = readAnnotation;
|
// this.ReadAnnotation = readAnnotation;
|
||||||
this.WriteAnnotation = writeAnnotation;
|
// this.WriteAnnotation = writeAnnotation;
|
||||||
this.ValueType = valueType;
|
// this.ValueType = valueType;
|
||||||
}
|
//}
|
||||||
|
|
||||||
public static PropertyTemplate MakePropertyTemplate(Type type, PropertyInfo pi, byte index = 0, string customName = null, TypeTemplate typeTemplate = null)
|
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)
|
if (propType == null)
|
||||||
throw new Exception($"Unsupported type `{pi.PropertyType}` in property `{type.Name}.{pi.Name}`");
|
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 storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
|
||||||
|
|
||||||
//var nullabilityContext = new NullabilityInfoContext();
|
//var nullabilityContext = new NullabilityInfoContext();
|
||||||
@@ -196,19 +254,46 @@ public class PropertyTemplate : MemberTemplate
|
|||||||
propType.SetNull(nullableAttrFlags);
|
propType.SetNull(nullableAttrFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
var pt = new PropertyTemplate(typeTemplate, index, customName ?? pi.Name, pi.DeclaringType != type, propType);
|
|
||||||
|
|
||||||
if (storageAttr != null)
|
Map<string, string> annotations = null;
|
||||||
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
|
||||||
|
|
||||||
if (annotationAttr != null)
|
if (annotationAttrs != null && annotationAttrs.Count() > 0)
|
||||||
pt.ReadAnnotation = annotationAttr.Annotation;
|
{
|
||||||
|
annotations = new Map<string, string>();
|
||||||
|
foreach (var attr in annotationAttrs)
|
||||||
|
annotations.Add(attr.Key, attr.Value);
|
||||||
|
}
|
||||||
else
|
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,
|
Resource,
|
||||||
Record,
|
Record,
|
||||||
Enum
|
Enum,
|
||||||
|
Function
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,9 @@ public class TypeTemplate
|
|||||||
protected UUID classId;
|
protected UUID classId;
|
||||||
protected UUID? parentId;
|
protected UUID? parentId;
|
||||||
|
|
||||||
public string Annotation { get; set; }
|
public Map<string, string> Annotations { get; set; }
|
||||||
|
|
||||||
string className;
|
string className;
|
||||||
List<MemberTemplate> members = new List<MemberTemplate>();
|
|
||||||
List<FunctionTemplate> functions = new List<FunctionTemplate>();
|
List<FunctionTemplate> functions = new List<FunctionTemplate>();
|
||||||
List<EventTemplate> events = new List<EventTemplate>();
|
List<EventTemplate> events = new List<EventTemplate>();
|
||||||
List<PropertyTemplate> properties = new List<PropertyTemplate>();
|
List<PropertyTemplate> properties = new List<PropertyTemplate>();
|
||||||
@@ -137,10 +136,10 @@ public class TypeTemplate
|
|||||||
get { return className; }
|
get { return className; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemberTemplate[] Methods
|
//public MemberTemplate[] Methods
|
||||||
{
|
//{
|
||||||
get { return members.ToArray(); }
|
// get { return members.ToArray(); }
|
||||||
}
|
//}
|
||||||
|
|
||||||
public FunctionTemplate[] Functions
|
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 bool IsWrapper { get; private set; }
|
||||||
|
|
||||||
public TypeTemplate(Type type, Warehouse warehouse = null)
|
public TypeTemplate(Type type, Warehouse warehouse = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
//if (!type.IsPublic)
|
|
||||||
// throw new Exception("Not public");
|
|
||||||
|
|
||||||
if (Codec.ImplementsInterface(type, typeof(IResource)))
|
if (Codec.ImplementsInterface(type, typeof(IResource)))
|
||||||
templateType = TemplateType.Resource;
|
templateType = TemplateType.Resource;
|
||||||
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
||||||
@@ -422,12 +399,6 @@ public class TypeTemplate
|
|||||||
|
|
||||||
IsWrapper = Codec.InheritsClass(type, typeof(DistributedResource));
|
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);
|
type = ResourceProxy.GetBaseType(type);
|
||||||
|
|
||||||
DefinedType = type;
|
DefinedType = type;
|
||||||
@@ -440,17 +411,6 @@ public class TypeTemplate
|
|||||||
if (warehouse != null)
|
if (warehouse != null)
|
||||||
warehouse.PutTemplate(this);
|
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);
|
var hierarchy = GetHierarchy(type);
|
||||||
|
|
||||||
if (hierarchy.ContainsKey(MemberTypes.Field))
|
if (hierarchy.ContainsKey(MemberTypes.Field))
|
||||||
@@ -505,19 +465,6 @@ public class TypeTemplate
|
|||||||
.MakeAttributeTemplate(type, attr, 0, attrAttr?.Name ?? attr.Name, this));
|
.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
|
// bake it binarily
|
||||||
var b = new BinaryList();
|
var b = new BinaryList();
|
||||||
@@ -526,8 +473,10 @@ public class TypeTemplate
|
|||||||
|
|
||||||
|
|
||||||
var hasParent = HasParent(type);
|
var hasParent = HasParent(type);
|
||||||
var classAnnotation = type.GetCustomAttribute<AnnotationAttribute>(false);
|
var classAnnotations = type.GetCustomAttributes<AnnotationAttribute>(false);
|
||||||
var hasClassAnnotation = classAnnotation != null && classAnnotation.Annotation != null;
|
|
||||||
|
|
||||||
|
var hasClassAnnotation = (classAnnotations != null) && (classAnnotations.Count() > 0);
|
||||||
|
|
||||||
var classNameBytes = DC.ToBytes(className);
|
var classNameBytes = DC.ToBytes(className);
|
||||||
|
|
||||||
@@ -546,15 +495,19 @@ public class TypeTemplate
|
|||||||
|
|
||||||
if (hasClassAnnotation)
|
if (hasClassAnnotation)
|
||||||
{
|
{
|
||||||
var classAnnotationBytes = DC.ToBytes(classAnnotation.Annotation);
|
Annotations = new Map<string, string>();
|
||||||
b.AddUInt16((ushort)classAnnotationBytes.Length)
|
|
||||||
.AddUInt8Array(classAnnotationBytes);
|
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)
|
b.AddInt32(version)
|
||||||
.AddUInt16((ushort)members.Count);
|
.AddUInt16((ushort)(functions.Count + properties.Count + events.Count + constants.Count));
|
||||||
|
|
||||||
foreach (var ft in functions)
|
foreach (var ft in functions)
|
||||||
b.AddUInt8Array(ft.Compose());
|
b.AddUInt8Array(ft.Compose());
|
||||||
@@ -758,9 +711,11 @@ public class TypeTemplate
|
|||||||
|
|
||||||
if (hasClassAnnotation)
|
if (hasClassAnnotation)
|
||||||
{
|
{
|
||||||
var len = data.GetUInt16(offset, Endian.Little);
|
var (len, anns) = Codec.ParseSync(data, offset, null);
|
||||||
offset += 2;
|
|
||||||
od.Annotation = data.GetString(offset, len);
|
if (anns is Map<string, string> annotations)
|
||||||
|
od.Annotations = annotations;
|
||||||
|
|
||||||
offset += len;
|
offset += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -781,151 +736,32 @@ public class TypeTemplate
|
|||||||
|
|
||||||
if (type == 0) // function
|
if (type == 0) // function
|
||||||
{
|
{
|
||||||
string annotation = null;
|
var (len, ft) = FunctionTemplate.Parse(data, offset, functionIndex++, inherited);
|
||||||
var isStatic = ((data[offset] & 0x4) == 0x4);
|
offset += len;
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
od.functions.Add(ft);
|
od.functions.Add(ft);
|
||||||
}
|
}
|
||||||
else if (type == 1) // property
|
else if (type == 1) // property
|
||||||
{
|
{
|
||||||
|
var (len, pt) = PropertyTemplate.Parse(data, offset, propertyIndex++, inherited);
|
||||||
string readAnnotation = null, writeAnnotation = null;
|
offset += len;
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
od.properties.Add(pt);
|
od.properties.Add(pt);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (type == 2) // Event
|
else if (type == 2) // Event
|
||||||
{
|
{
|
||||||
|
var (len, et) = EventTemplate.Parse(data, offset, propertyIndex++, inherited);
|
||||||
string annotation = null;
|
offset += len;
|
||||||
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);
|
|
||||||
|
|
||||||
od.events.Add(et);
|
od.events.Add(et);
|
||||||
|
|
||||||
}
|
}
|
||||||
// constant
|
// constant
|
||||||
else if (type == 3)
|
else if (type == 3)
|
||||||
{
|
{
|
||||||
string annotation = null;
|
var (len, ct) = ConstantTemplate.Parse(data, offset, propertyIndex++, inherited);
|
||||||
var hasAnnotation = ((data[offset++] & 0x10) == 0x10);
|
offset += len;
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
od.constants.Add(ct);
|
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;
|
return od;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -425,7 +425,7 @@ public class Warehouse
|
|||||||
/// <param name="resource">Resource instance.</param>
|
/// <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="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>
|
/// <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)
|
if (resource.Instance != null)
|
||||||
throw new Exception("Resource already initialized.");
|
throw new Exception("Resource already initialized.");
|
||||||
@@ -464,7 +464,7 @@ public class Warehouse
|
|||||||
|
|
||||||
var resourceReference = new WeakReference<IResource>(resource);
|
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 != null)
|
||||||
if (attributes is Map<string, object> attrs)
|
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)
|
public async AsyncReply<IResource> New(Type type, string path, IPermissionsManager manager = null, object attributes = null, object properties = null)
|
||||||
{
|
{
|
||||||
var res = Create(type, properties);
|
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)
|
public async AsyncReply<T> New<T>(string path, IPermissionsManager manager = null, object attributes = null, object properties = null)
|
||||||
|
|||||||
Reference in New Issue
Block a user