mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-05-06 11:32:59 +00:00
Static Arrays
This commit is contained in:
parent
d6b2a27221
commit
7940c152f0
@ -9,7 +9,7 @@
|
||||
<Product>Esiur Entity Framework Extension</Product>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageId>Esiur.Stores.EntityCore</PackageId>
|
||||
<Version>1.2.1</Version>
|
||||
<Version>1.2.3</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/esiur/esiur-dotnet/</RepositoryUrl>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Version>1.5.0</Version>
|
||||
<Version>1.5.2</Version>
|
||||
<PackageId>Esiur.Stores.MongoDB</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -52,10 +52,10 @@ namespace Esiur.Stores.MongoDB
|
||||
|
||||
|
||||
[Public]
|
||||
public event ResourceEventHanlder<IResource> ResourceAdded;
|
||||
public event ResourceEventHandler<IResource> ResourceAdded;
|
||||
|
||||
[Public]
|
||||
public event ResourceEventHanlder<IResource> ResourceRemoved;
|
||||
public event ResourceEventHandler<IResource> ResourceRemoved;
|
||||
|
||||
int count = 0;
|
||||
|
||||
|
@ -40,6 +40,8 @@ namespace Esiur.Core
|
||||
bool sealedBag = false;
|
||||
|
||||
|
||||
public Type ArrayType { get; set; }
|
||||
|
||||
public AsyncBag Then(Action<object[]> callback)
|
||||
{
|
||||
base.Then(new Action<object>(o => callback((object[])o)));
|
||||
@ -82,7 +84,17 @@ namespace Esiur.Core
|
||||
results[index] = r;
|
||||
count++;
|
||||
if (count == results.Count)
|
||||
{
|
||||
if (ArrayType != null)
|
||||
{
|
||||
var ar = Array.CreateInstance(ArrayType, count);
|
||||
for (var i = 0; i < count; i++)
|
||||
ar.SetValue(results[i], i);
|
||||
Trigger(ar);
|
||||
}
|
||||
else
|
||||
Trigger(results.ToArray());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -255,10 +255,10 @@ namespace Esiur.Data
|
||||
}
|
||||
|
||||
|
||||
public static AsyncBag<IRecord> ParseRecordArray(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
public static AsyncBag ParseRecordArray(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
var reply = new AsyncBag();
|
||||
|
||||
var reply = new AsyncBag<IRecord>();
|
||||
if (length == 0)
|
||||
{
|
||||
reply.Seal();
|
||||
@ -267,8 +267,59 @@ namespace Esiur.Data
|
||||
|
||||
var end = offset + length;
|
||||
|
||||
var result = (RecordComparisonResult)data[offset++];
|
||||
var isTyped = (data[offset] & 0x10) == 0x10;
|
||||
|
||||
var result = (RecordComparisonResult)(data[offset++] & 0xF);
|
||||
|
||||
if (isTyped)
|
||||
{
|
||||
var classId = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
|
||||
var template = Warehouse.GetTemplateByClassId(classId, TemplateType.Record);
|
||||
|
||||
reply.ArrayType = template.DefinedType;
|
||||
|
||||
AsyncReply<IRecord> previous = null;
|
||||
|
||||
if (result == RecordComparisonResult.Null)
|
||||
previous = new AsyncReply<IRecord>(null);
|
||||
else if (result == RecordComparisonResult.Record
|
||||
|| result == RecordComparisonResult.RecordSameType)
|
||||
{
|
||||
uint cs = data.GetUInt32(offset);
|
||||
uint recordLength = cs;
|
||||
offset += 4;
|
||||
previous = ParseRecord(data, offset, recordLength, connection, classId);
|
||||
offset += recordLength;
|
||||
}
|
||||
|
||||
reply.Add(previous);
|
||||
|
||||
while (offset < end)
|
||||
{
|
||||
result = (RecordComparisonResult)data[offset++];
|
||||
|
||||
if (result == RecordComparisonResult.Null)
|
||||
previous = new AsyncReply<IRecord>(null);
|
||||
else if (result == RecordComparisonResult.Record
|
||||
|| result == RecordComparisonResult.RecordSameType)
|
||||
{
|
||||
uint cs = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
previous = ParseRecord(data, offset, cs, connection, classId);
|
||||
offset += cs;
|
||||
}
|
||||
else if (result == RecordComparisonResult.Same)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
reply.Add(previous);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AsyncReply<IRecord> previous = null;
|
||||
Guid? classId = null;
|
||||
|
||||
@ -319,6 +370,8 @@ namespace Esiur.Data
|
||||
reply.Add(previous);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
reply.Seal();
|
||||
return reply;
|
||||
}
|
||||
@ -335,15 +388,15 @@ namespace Esiur.Data
|
||||
length -= 16;
|
||||
}
|
||||
|
||||
var template = Warehouse.GetTemplateByClassId((Guid)classId);
|
||||
var template = Warehouse.GetTemplateByClassId((Guid)classId, TemplateType.Record);
|
||||
|
||||
if (template != null)
|
||||
{
|
||||
ParseVarArray(data, offset, length, connection).Then(ar =>
|
||||
{
|
||||
if (template.ResourceType != null)
|
||||
if (template.DefinedType != null)
|
||||
{
|
||||
var record = Activator.CreateInstance(template.ResourceType) as IRecord;
|
||||
var record = Activator.CreateInstance(template.DefinedType) as IRecord;
|
||||
for (var i = 0; i < template.Properties.Length; i++)
|
||||
template.Properties[i].PropertyInfo.SetValue(record, ar[i]);
|
||||
|
||||
@ -399,7 +452,8 @@ namespace Esiur.Data
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] ComposeRecordArray(IRecord[] records, DistributedConnection connection, bool prependLength = false)
|
||||
public static byte[] ComposeRecordArray<T>(T[] records, DistributedConnection connection, bool prependLength = false)
|
||||
where T : IRecord
|
||||
{
|
||||
|
||||
if (records == null || records?.Length == 0)
|
||||
@ -408,8 +462,41 @@ namespace Esiur.Data
|
||||
var rt = new BinaryList();
|
||||
var comparsion = Compare(null, records[0]);
|
||||
|
||||
var type = records.GetType().GetElementType();
|
||||
var isTyped = type != typeof(IRecord);
|
||||
|
||||
if (isTyped)
|
||||
{
|
||||
var template = Warehouse.GetTemplateByType(type);
|
||||
|
||||
if (template != null)
|
||||
{
|
||||
// typed array ... no need to add class id , it will be included at the first entry
|
||||
rt.AddUInt8((byte)(0x10 | (byte)comparsion));
|
||||
rt.AddGuid(template.ClassId);
|
||||
}
|
||||
else // something wrong
|
||||
{
|
||||
throw new Exception($"Template for type `{type.FullName}` not found.");
|
||||
}
|
||||
|
||||
if (comparsion == RecordComparisonResult.Record)
|
||||
rt.AddUInt8Array(ComposeRecord(records[0], connection, false, true));
|
||||
|
||||
for (var i = 1; i < records.Length; i++)
|
||||
{
|
||||
comparsion = Compare(records[i - 1], records[i]);
|
||||
|
||||
rt.AddUInt8((byte)comparsion);
|
||||
|
||||
if (comparsion == RecordComparisonResult.RecordSameType
|
||||
|| comparsion == RecordComparisonResult.Record)
|
||||
rt.AddUInt8Array(ComposeRecord(records[i], connection, false, true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt.AddUInt8((byte)comparsion);
|
||||
|
||||
if (comparsion == RecordComparisonResult.Record)
|
||||
rt.AddUInt8Array(ComposeRecord(records[0], connection, true, true));
|
||||
@ -417,6 +504,7 @@ namespace Esiur.Data
|
||||
for (var i = 1; i < records.Length; i++)
|
||||
{
|
||||
comparsion = Compare(records[i - 1], records[i]);
|
||||
|
||||
rt.AddUInt8((byte)comparsion);
|
||||
|
||||
if (comparsion == RecordComparisonResult.Record)
|
||||
@ -424,6 +512,8 @@ namespace Esiur.Data
|
||||
else if (comparsion == RecordComparisonResult.RecordSameType)
|
||||
rt.AddUInt8Array(ComposeRecord(records[i], connection, false, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (prependLength)
|
||||
rt.InsertInt32(0, rt.Length);
|
||||
@ -839,15 +929,40 @@ namespace Esiur.Data
|
||||
/// <param name="connection">DistributedConnection is required to check locality.</param>
|
||||
/// <param name="prependLength">If True, prepend the length of the output at the beginning.</param>
|
||||
/// <returns>Array of bytes in the network byte order.</returns>
|
||||
public static byte[] ComposeResourceArray(IResource[] resources, DistributedConnection connection, bool prependLength = false)
|
||||
public static byte[] ComposeResourceArray<T>(T[] resources, DistributedConnection connection, bool prependLength = false)
|
||||
where T : IResource
|
||||
{
|
||||
|
||||
if (resources == null || resources?.Length == 0)
|
||||
return prependLength ? new byte[] { 0, 0, 0, 0 } : new byte[0];
|
||||
|
||||
var rt = new BinaryList();
|
||||
var comparsion = Compare(null, resources[0], connection);
|
||||
|
||||
var type = resources.GetType().GetElementType();
|
||||
|
||||
|
||||
if (type != typeof(IResource))
|
||||
{
|
||||
// get template
|
||||
var tmp = Warehouse.GetTemplateByType(type);
|
||||
|
||||
if (tmp == null) // something wrong
|
||||
rt.AddUInt8((byte)comparsion);
|
||||
else
|
||||
{
|
||||
// typed array
|
||||
rt.AddUInt8((byte)((byte)( tmp.Type == TemplateType.Resource ? ResourceArrayType.Static : ResourceArrayType.Wrapper)
|
||||
| (byte)comparsion));
|
||||
// add type
|
||||
rt.AddGuid(tmp.ClassId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt.AddUInt8((byte)comparsion);
|
||||
}
|
||||
|
||||
|
||||
if (comparsion == ResourceComparisonResult.Local)
|
||||
rt.AddUInt32((resources[0] as DistributedResource).Id);
|
||||
@ -889,8 +1004,29 @@ namespace Esiur.Data
|
||||
|
||||
var end = offset + length;
|
||||
|
||||
//
|
||||
var result = (ResourceComparisonResult)data[offset++];
|
||||
// Is typed array ?
|
||||
var type = (ResourceArrayType) (data[offset] & 0xF0);
|
||||
|
||||
var result = (ResourceComparisonResult)(data[offset++] & 0xF);
|
||||
|
||||
|
||||
if (type == ResourceArrayType.Wrapper)
|
||||
{
|
||||
var classId = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
var tmp = Warehouse.GetTemplateByClassId(classId, TemplateType.Resource);
|
||||
// not mine, look if the type is elsewhere
|
||||
if (tmp == null)
|
||||
Warehouse.GetTemplateByClassId(classId, TemplateType.Wrapper);
|
||||
reply.ArrayType = tmp?.DefinedType;
|
||||
}
|
||||
else if (type == ResourceArrayType.Static)
|
||||
{
|
||||
var classId = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
var tmp = Warehouse.GetTemplateByClassId(classId, TemplateType.Wrapper);
|
||||
reply.ArrayType = tmp?.DefinedType;
|
||||
}
|
||||
|
||||
AsyncReply previous = null;
|
||||
|
||||
@ -1236,11 +1372,14 @@ namespace Esiur.Data
|
||||
break;
|
||||
|
||||
case DataType.ResourceArray:
|
||||
if (value is IResource[])
|
||||
|
||||
rt.AddUInt8Array(ComposeResourceArray((IResource[])value, connection, true));
|
||||
else
|
||||
rt.AddUInt8Array(ComposeResourceArray((IResource[])DC.CastConvert(value, typeof(IResource[])), connection, true));
|
||||
break;
|
||||
//if (value is IResource[])
|
||||
// rt.AddUInt8Array(ComposeResourceArray((IResource[])value, connection, true));
|
||||
//else
|
||||
// rt.AddUInt8Array(ComposeResourceArray((IResource[])DC.CastConvert(value, typeof(IResource[])), connection, true));
|
||||
//break;
|
||||
|
||||
case DataType.StructureArray:
|
||||
rt.AddUInt8Array(ComposeStructureArray((Structure[])value, connection, true));
|
||||
@ -1281,38 +1420,6 @@ namespace Esiur.Data
|
||||
/// <returns>True, if <paramref name="type"/> implements <paramref name="iface"/>.</returns>
|
||||
public static bool ImplementsInterface(Type type, Type iface)
|
||||
{
|
||||
/*
|
||||
if (iface.GetTypeInfo().IsGenericType)
|
||||
{
|
||||
//var x = (type.GetTypeInfo().GetInterfaces().Any(x => x.GetTypeInfo().IsGenericType Contains(iface))
|
||||
|
||||
iface = iface.GetTypeInfo().GetGenericTypeDefinition();
|
||||
|
||||
//if (type.GetTypeInfo().IsGenericType)
|
||||
// type =
|
||||
while (type != null)
|
||||
{
|
||||
if (type == iface)
|
||||
return true;
|
||||
|
||||
#if NETSTANDARD
|
||||
if (type.GetTypeInfo().GetInterfaces().Contains(iface))// (x=>x.GetTypeInfo().IsGenericType (iface))
|
||||
return true;
|
||||
|
||||
type = type.GetTypeInfo().BaseType;
|
||||
#else
|
||||
if (type.GetInterfaces().Contains(iface))
|
||||
return true;
|
||||
type = type.BaseType;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
*/
|
||||
//{
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
if (type == iface)
|
||||
@ -1330,10 +1437,12 @@ namespace Esiur.Data
|
||||
#endif
|
||||
}
|
||||
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool InheritsClass(Type type, Type parent)
|
||||
=> type.IsSubclassOf(parent);
|
||||
|
||||
/// <summary>
|
||||
/// Check if a type inherits another type.
|
||||
/// </summary>
|
||||
|
13
Esiur/Data/ResourceArrayType.cs
Normal file
13
Esiur/Data/ResourceArrayType.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data
|
||||
{
|
||||
public enum ResourceArrayType
|
||||
{
|
||||
Dynamic = 0x0,
|
||||
Static = 0x10,
|
||||
Wrapper = 0x20,
|
||||
}
|
||||
}
|
@ -6,9 +6,9 @@ namespace Esiur.Data
|
||||
{
|
||||
public enum ResourceComparisonResult
|
||||
{
|
||||
Null,
|
||||
Distributed,
|
||||
Local,
|
||||
Same
|
||||
Null, // null
|
||||
Distributed, // resource is distributed
|
||||
Local, // resource is local
|
||||
Same, // Same as previous
|
||||
}
|
||||
}
|
||||
|
@ -7,12 +7,12 @@
|
||||
<PackageLicenseUrl>https://github.com/Esiur/Esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
|
||||
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Version>1.8.2.18</Version>
|
||||
<Version>1.8.5</Version>
|
||||
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
|
||||
<Authors>Ahmed Kh. Zamil</Authors>
|
||||
<AssemblyVersion>1.8.1.0</AssemblyVersion>
|
||||
<AssemblyVersion>1.8.5.0</AssemblyVersion>
|
||||
<Company>Esiur Foundation</Company>
|
||||
<FileVersion>1.8.1.0</FileVersion>
|
||||
<FileVersion>1.8.5.0</FileVersion>
|
||||
<AssemblyName>Esiur</AssemblyName>
|
||||
<RootNamespace>Esiur</RootNamespace>
|
||||
<PackageId>Esiur</PackageId>
|
||||
@ -41,7 +41,6 @@
|
||||
<Compile Remove="Resource\ResourceEvent.cs" />
|
||||
<Compile Remove="Resource\ResourceFunction.cs" />
|
||||
<Compile Remove="Resource\ResourceProperty.cs" />
|
||||
<Compile Remove="Resource\Template\RecordTemplate.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -54,7 +53,6 @@
|
||||
<None Include="Resource\ResourceEvent.cs" />
|
||||
<None Include="Resource\ResourceFunction.cs" />
|
||||
<None Include="Resource\ResourceProperty.cs" />
|
||||
<None Include="Resource\Template\RecordTemplate.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -556,7 +556,7 @@ namespace Esiur.Net.IIP
|
||||
case IIPPacket.IIPPacketAction.TemplateFromClassName:
|
||||
case IIPPacket.IIPPacketAction.TemplateFromClassId:
|
||||
case IIPPacket.IIPPacketAction.TemplateFromResourceId:
|
||||
IIPReply(packet.CallbackId, ResourceTemplate.Parse(packet.Content));
|
||||
IIPReply(packet.CallbackId, TypeTemplate.Parse(packet.Content));
|
||||
break;
|
||||
|
||||
case IIPPacketAction.QueryLink:
|
||||
|
@ -44,12 +44,12 @@ namespace Esiur.Net.IIP
|
||||
{
|
||||
KeyList<uint, DistributedResource> resources = new KeyList<uint, DistributedResource>();
|
||||
KeyList<uint, AsyncReply<DistributedResource>> resourceRequests = new KeyList<uint, AsyncReply<DistributedResource>>();
|
||||
KeyList<Guid, AsyncReply<ResourceTemplate>> templateRequests = new KeyList<Guid, AsyncReply<ResourceTemplate>>();
|
||||
KeyList<Guid, AsyncReply<TypeTemplate>> templateRequests = new KeyList<Guid, AsyncReply<TypeTemplate>>();
|
||||
|
||||
|
||||
KeyList<string, AsyncReply<IResource>> pathRequests = new KeyList<string, AsyncReply<IResource>>();
|
||||
|
||||
Dictionary<Guid, ResourceTemplate> templates = new Dictionary<Guid, ResourceTemplate>();
|
||||
Dictionary<Guid, TypeTemplate> templates = new Dictionary<Guid, TypeTemplate>();
|
||||
|
||||
KeyList<uint, AsyncReply> requests = new KeyList<uint, AsyncReply>();
|
||||
|
||||
@ -1095,11 +1095,11 @@ namespace Esiur.Net.IIP
|
||||
|
||||
var msg = new BinaryList();
|
||||
|
||||
var templates = new List<ResourceTemplate>();
|
||||
var templates = new List<TypeTemplate>();
|
||||
foreach (var resource in list)
|
||||
templates.AddRange(ResourceTemplate.GetDependencies(resource.Instance.Template).Where(x => !templates.Contains(x)));
|
||||
templates.AddRange(TypeTemplate.GetDependencies(resource.Instance.Template).Where(x => !templates.Contains(x)));
|
||||
|
||||
foreach(var t in templates)
|
||||
foreach (var t in templates)
|
||||
{
|
||||
msg.AddInt32(t.Content.Length)
|
||||
.AddUInt8Array(t.Content);
|
||||
@ -1122,8 +1122,8 @@ namespace Esiur.Net.IIP
|
||||
|
||||
void IIPRequestTemplateFromClassName(uint callback, string className)
|
||||
{
|
||||
Warehouse.GetTemplateByClassName(className).Then((t) =>
|
||||
{
|
||||
var t = Warehouse.GetTemplateByClassName(className);
|
||||
|
||||
if (t != null)
|
||||
SendReply(IIPPacket.IIPPacketAction.TemplateFromClassName, callback)
|
||||
.AddInt32(t.Content.Length)
|
||||
@ -1134,7 +1134,6 @@ namespace Esiur.Net.IIP
|
||||
// reply failed
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void IIPRequestTemplateFromClassId(uint callback, Guid classId)
|
||||
@ -2037,14 +2036,14 @@ namespace Esiur.Net.IIP
|
||||
/// </summary>
|
||||
/// <param name="classId">Class GUID.</param>
|
||||
/// <returns>ResourceTemplate.</returns>
|
||||
public AsyncReply<ResourceTemplate> GetTemplate(Guid classId)
|
||||
public AsyncReply<TypeTemplate> GetTemplate(Guid classId)
|
||||
{
|
||||
if (templates.ContainsKey(classId))
|
||||
return new AsyncReply<ResourceTemplate>(templates[classId]);
|
||||
return new AsyncReply<TypeTemplate>(templates[classId]);
|
||||
else if (templateRequests.ContainsKey(classId))
|
||||
return templateRequests[classId];
|
||||
|
||||
var reply = new AsyncReply<ResourceTemplate>();
|
||||
var reply = new AsyncReply<TypeTemplate>();
|
||||
templateRequests.Add(classId, reply);
|
||||
|
||||
SendRequest(IIPPacket.IIPPacketAction.TemplateFromClassId)
|
||||
@ -2053,8 +2052,8 @@ namespace Esiur.Net.IIP
|
||||
.Then((rt) =>
|
||||
{
|
||||
templateRequests.Remove(classId);
|
||||
templates.Add(((ResourceTemplate)rt[0]).ClassId, (ResourceTemplate)rt[0]);
|
||||
Warehouse.PutTemplate(rt[0] as ResourceTemplate);
|
||||
templates.Add(((TypeTemplate)rt[0]).ClassId, (TypeTemplate)rt[0]);
|
||||
Warehouse.PutTemplate(rt[0] as TypeTemplate);
|
||||
reply.Trigger(rt[0]);
|
||||
}).Error((ex) =>
|
||||
{
|
||||
@ -2134,9 +2133,9 @@ namespace Esiur.Net.IIP
|
||||
}
|
||||
|
||||
|
||||
public AsyncReply<ResourceTemplate[]> GetLinkTemplates(string link)
|
||||
public AsyncReply<TypeTemplate[]> GetLinkTemplates(string link)
|
||||
{
|
||||
var reply = new AsyncReply<ResourceTemplate[]>();
|
||||
var reply = new AsyncReply<TypeTemplate[]>();
|
||||
|
||||
var l = DC.ToBytes(link);
|
||||
|
||||
@ -2147,7 +2146,7 @@ namespace Esiur.Net.IIP
|
||||
.Then((rt) =>
|
||||
{
|
||||
|
||||
var templates = new List<ResourceTemplate>();
|
||||
var templates = new List<TypeTemplate>();
|
||||
// parse templates
|
||||
|
||||
var data = (byte[])rt[0];
|
||||
@ -2156,7 +2155,7 @@ namespace Esiur.Net.IIP
|
||||
{
|
||||
var cs = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
templates.Add(ResourceTemplate.Parse(data, offset, cs));
|
||||
templates.Add(TypeTemplate.Parse(data, offset, cs));
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
@ -2208,9 +2207,9 @@ namespace Esiur.Net.IIP
|
||||
|
||||
if (resource == null)
|
||||
{
|
||||
var template = Warehouse.GetTemplateByClassId((Guid)rt[0], true);
|
||||
if (template?.ResourceType != null)
|
||||
dr = Activator.CreateInstance(template.ResourceType, this, id, (ulong)rt[1], (string)rt[2]) as DistributedResource;
|
||||
var template = Warehouse.GetTemplateByClassId((Guid)rt[0], TemplateType.Wrapper);
|
||||
if (template?.DefinedType != null)
|
||||
dr = Activator.CreateInstance(template.DefinedType, this, id, (ulong)rt[1], (string)rt[2]) as DistributedResource;
|
||||
else
|
||||
dr = new DistributedResource(this, id, (ulong)rt[1], (string)rt[2]);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace Esiur.Proxy
|
||||
|
||||
|
||||
|
||||
private KeyList<string, ResourceTemplate[]> cache = new();
|
||||
private KeyList<string, TypeTemplate[]> cache = new();
|
||||
// private List<string> inProgress = new();
|
||||
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
@ -41,7 +41,7 @@ namespace Esiur.Proxy
|
||||
|
||||
|
||||
|
||||
void GenerateModel(GeneratorExecutionContext context, ResourceTemplate[] templates)
|
||||
void GenerateModel(GeneratorExecutionContext context, TypeTemplate[] templates)
|
||||
{
|
||||
foreach (var tmp in templates)
|
||||
{
|
||||
@ -126,7 +126,7 @@ namespace Esiur.Proxy
|
||||
catch (Exception ex)
|
||||
{
|
||||
ReportError(context, ex.Source, ex.Message, "Esiur");
|
||||
System.IO.File.AppendAllText("c:\\gen\\error.log", ex.ToString() + "\r\n");
|
||||
//System.IO.File.AppendAllText("c:\\gen\\error.log", ex.ToString() + "\r\n");
|
||||
}
|
||||
|
||||
//inProgress.Remove(path);
|
||||
|
@ -16,7 +16,7 @@ namespace Esiur.Proxy
|
||||
{
|
||||
internal static Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)");
|
||||
|
||||
internal static string GenerateRecord(ResourceTemplate template, ResourceTemplate[] templates)
|
||||
internal static string GenerateRecord(TypeTemplate template, TypeTemplate[] templates)
|
||||
{
|
||||
var cls = template.ClassName.Split('.');
|
||||
|
||||
@ -42,7 +42,7 @@ namespace Esiur.Proxy
|
||||
return rt.ToString();
|
||||
}
|
||||
|
||||
static string GetTypeName(TemplateDataType templateDataType, ResourceTemplate[] templates)
|
||||
static string GetTypeName(TemplateDataType templateDataType, TypeTemplate[] templates)
|
||||
{
|
||||
|
||||
if (templateDataType.Type == DataType.Resource)
|
||||
@ -162,7 +162,7 @@ namespace Esiur.Proxy
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GenerateClass(ResourceTemplate template, ResourceTemplate[] templates)
|
||||
internal static string GenerateClass(TypeTemplate template, TypeTemplate[] templates)
|
||||
{
|
||||
var cls = template.ClassName.Split('.');
|
||||
|
||||
@ -213,7 +213,7 @@ namespace Esiur.Proxy
|
||||
{
|
||||
var etTypeName = GetTypeName(e.ArgumentType, templates);
|
||||
rt.AppendLine($"case {e.Index}: {e.Name}?.Invoke(({etTypeName})args); break;");
|
||||
eventsList.AppendLine($"public event ResourceEventHanlder<{etTypeName}> {e.Name};");
|
||||
eventsList.AppendLine($"public event ResourceEventHandler<{etTypeName}> {e.Name};");
|
||||
}
|
||||
|
||||
rt.AppendLine("}}");
|
||||
|
@ -28,7 +28,7 @@ namespace Esiur.Resource
|
||||
|
||||
WeakReference<IResource> resource;
|
||||
IStore store;
|
||||
ResourceTemplate template;
|
||||
TypeTemplate template;
|
||||
AutoList<IPermissionsManager, Instance> managers;
|
||||
|
||||
|
||||
@ -794,7 +794,7 @@ namespace Esiur.Resource
|
||||
/// <summary>
|
||||
/// Resource template describes the properties, functions and events of the resource.
|
||||
/// </summary>
|
||||
public ResourceTemplate Template
|
||||
public TypeTemplate Template
|
||||
{
|
||||
get { return template; }
|
||||
|
||||
@ -853,7 +853,7 @@ namespace Esiur.Resource
|
||||
/// <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(uint id, string name, IResource resource, IStore store, ResourceTemplate customTemplate = null, ulong age = 0)
|
||||
public Instance(uint id, string name, IResource resource, IStore store, TypeTemplate customTemplate = null, ulong age = 0)
|
||||
{
|
||||
this.store = store;
|
||||
this.resource = new WeakReference<IResource>(resource);
|
||||
@ -897,7 +897,7 @@ namespace Esiur.Resource
|
||||
|
||||
foreach (var evt in template.Events)
|
||||
{
|
||||
//if (evt.EventHandlerType != typeof(ResourceEventHanlder))
|
||||
//if (evt.EventHandlerType != typeof(ResourceEventHandler))
|
||||
// continue;
|
||||
|
||||
if (evt.EventInfo == null)
|
||||
@ -905,24 +905,24 @@ namespace Esiur.Resource
|
||||
|
||||
var eventGenericType = evt.EventInfo.EventHandlerType.GetGenericTypeDefinition();
|
||||
|
||||
if (eventGenericType == typeof(ResourceEventHanlder<>))
|
||||
if (eventGenericType == typeof(ResourceEventHandler<>))
|
||||
{
|
||||
|
||||
// var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
|
||||
// if (ca.Length == 0)
|
||||
// continue;
|
||||
|
||||
ResourceEventHanlder<object> proxyDelegate = (args) => EmitResourceEvent(evt.Name, args);
|
||||
ResourceEventHandler<object> proxyDelegate = (args) => EmitResourceEvent(evt.Name, args);
|
||||
evt.EventInfo.AddEventHandler(resource, proxyDelegate);
|
||||
|
||||
}
|
||||
else if (eventGenericType == typeof(CustomResourceEventHanlder<>))
|
||||
else if (eventGenericType == typeof(CustomResourceEventHandler<>))
|
||||
{
|
||||
//var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
|
||||
//if (ca.Length == 0)
|
||||
// continue;
|
||||
|
||||
CustomResourceEventHanlder<object> proxyDelegate = (issuer, receivers, args) => EmitCustomResourceEvent(issuer, receivers, evt.Name, args);
|
||||
CustomResourceEventHandler<object> proxyDelegate = (issuer, receivers, args) => EmitCustomResourceEvent(issuer, receivers, evt.Name, args);
|
||||
evt.EventInfo.AddEventHandler(resource, proxyDelegate);
|
||||
}
|
||||
|
||||
|
@ -35,12 +35,12 @@ namespace Esiur.Resource
|
||||
{
|
||||
public delegate R DCovariant<out R>();
|
||||
|
||||
public delegate void ResourceEventHanlder<in T>(T argument);
|
||||
public delegate void ResourceEventHandler<in T>(T argument);
|
||||
// public delegate void CustomUsersEventHanlder(string[] usernames, params object[] args);
|
||||
//public delegate void CustomReceiversEventHanlder(DistributedConnection[] connections, params object[] args);
|
||||
//public delegate void CustomInquirerEventHanlder(object inquirer, params object[] args);
|
||||
|
||||
public delegate void CustomResourceEventHanlder<in T>(object issuer, Func<Session, bool> receivers, T argument);// object issuer, Session[] receivers, params object[] args);
|
||||
public delegate void CustomResourceEventHandler<in T>(object issuer, Func<Session, bool> receivers, T argument);// object issuer, Session[] receivers, params object[] args);
|
||||
|
||||
// public delegate void CustomReceiversEventHanlder(string[] usernames, DistributedConnection[] connections, params object[] args);
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace Esiur.Resource.Template
|
||||
}
|
||||
|
||||
|
||||
public AttributeTemplate(ResourceTemplate template, byte index, string name)
|
||||
public AttributeTemplate(TypeTemplate template, byte index, string name)
|
||||
: base(template, MemberType.Attribute, index, name)
|
||||
{
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace Esiur.Resource.Template
|
||||
}
|
||||
|
||||
|
||||
public EventTemplate(ResourceTemplate template, byte index, string name, TemplateDataType argumentType, string expansion = null, bool listenable=false)
|
||||
public EventTemplate(TypeTemplate template, byte index, string name, TemplateDataType argumentType, string expansion = null, bool listenable=false)
|
||||
:base(template, MemberType.Property, index, name)
|
||||
{
|
||||
this.Expansion = expansion;
|
||||
|
@ -64,7 +64,7 @@ namespace Esiur.Resource.Template
|
||||
}
|
||||
|
||||
|
||||
public FunctionTemplate(ResourceTemplate template, byte index, string name, ArgumentTemplate[] arguments, TemplateDataType returnType, string expansion = null)
|
||||
public FunctionTemplate(TypeTemplate template, byte index, string name, ArgumentTemplate[] arguments, TemplateDataType returnType, string expansion = null)
|
||||
: base(template, MemberType.Property, index, name)
|
||||
{
|
||||
//this.IsVoid = isVoid;
|
||||
|
@ -21,14 +21,14 @@ namespace Esiur.Resource.Template
|
||||
public string Name => name;
|
||||
public MemberType Type => type;
|
||||
|
||||
ResourceTemplate template;
|
||||
TypeTemplate template;
|
||||
string name;
|
||||
MemberType type;
|
||||
byte index;
|
||||
|
||||
public ResourceTemplate Template => template;
|
||||
public TypeTemplate Template => template;
|
||||
|
||||
public MemberTemplate(ResourceTemplate template, MemberType type, byte index, string name)
|
||||
public MemberTemplate(TypeTemplate template, MemberType type, byte index, string name)
|
||||
{
|
||||
this.template = template;
|
||||
this.type = type;
|
||||
|
@ -130,7 +130,7 @@ namespace Esiur.Resource.Template
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyTemplate(ResourceTemplate template, byte index, string name, TemplateDataType valueType, string read = null, string write = null, bool recordable = false)
|
||||
public PropertyTemplate(TypeTemplate template, byte index, string name, TemplateDataType valueType, string read = null, string write = null, bool recordable = false)
|
||||
: base(template, MemberType.Property, index, name)
|
||||
{
|
||||
this.Recordable = recordable;
|
||||
|
@ -1,277 +0,0 @@
|
||||
using Esiur.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Resource.Template
|
||||
{
|
||||
public class RecordTemplate : ResourceTemplate
|
||||
{
|
||||
//Guid classId;
|
||||
//public Guid ClassId => classId;
|
||||
|
||||
//string className;
|
||||
//public string ClassName => className;
|
||||
|
||||
public RecordTemplate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public new static RecordTemplate Parse(byte[] data, uint offset, uint contentLength)
|
||||
{
|
||||
|
||||
uint ends = offset + contentLength;
|
||||
|
||||
uint oOffset = offset;
|
||||
|
||||
// start parsing...
|
||||
|
||||
var od = new RecordTemplate();
|
||||
od.content = data.Clip(offset, contentLength);
|
||||
|
||||
od.classId = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
od.className = data.GetString(offset + 1, data[offset]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
od.version = data.GetInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
ushort methodsCount = data.GetUInt16(offset);
|
||||
offset += 2;
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < methodsCount; i++)
|
||||
{
|
||||
var type = data[offset] >> 5;
|
||||
|
||||
if (type == 0) // function
|
||||
{
|
||||
string expansion = null;
|
||||
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
|
||||
|
||||
var name = data.GetString(offset + 1, data[offset]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
|
||||
// return type
|
||||
var (rts, returnType) = TemplateDataType.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);
|
||||
arguments.Add(argType);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
// arguments
|
||||
if (hasExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
expansion = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var ft = new FunctionTemplate(od, functionIndex++, name, arguments.ToArray(), returnType, expansion);
|
||||
|
||||
od.functions.Add(ft);
|
||||
}
|
||||
else if (type == 1) // property
|
||||
{
|
||||
|
||||
string readExpansion = null, writeExpansion = null;
|
||||
|
||||
var hasReadExpansion = ((data[offset] & 0x8) == 0x8);
|
||||
var hasWriteExpansion = ((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) = TemplateDataType.Parse(data, offset);
|
||||
|
||||
offset += dts;
|
||||
|
||||
if (hasReadExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
readExpansion = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
if (hasWriteExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
writeExpansion = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var pt = new PropertyTemplate(od, propertyIndex++, name, valueType, readExpansion, writeExpansion, recordable);
|
||||
|
||||
od.properties.Add(pt);
|
||||
}
|
||||
else if (type == 2) // Event
|
||||
{
|
||||
|
||||
string expansion = null;
|
||||
var hasExpansion = ((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) = TemplateDataType.Parse(data, offset);
|
||||
|
||||
offset += dts;
|
||||
|
||||
if (hasExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
expansion = data.GetString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var et = new EventTemplate(od, eventIndex++, name, argType, expansion, listenable);
|
||||
|
||||
od.events.Add(et);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 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]);
|
||||
|
||||
|
||||
//od.isReady = true;
|
||||
/*
|
||||
var oo = owner.Socket.Engine.GetObjectDescription(od.GUID);
|
||||
if (oo != null)
|
||||
{
|
||||
Console.WriteLine("Already there ! description");
|
||||
return oo;
|
||||
}
|
||||
else
|
||||
{
|
||||
owner.Socket.Engine.AddObjectDescription(od);
|
||||
return od;
|
||||
}
|
||||
*/
|
||||
|
||||
return od;
|
||||
}
|
||||
|
||||
public RecordTemplate(Type type)
|
||||
{
|
||||
if (!Codec.ImplementsInterface(type, typeof(IRecord)))
|
||||
throw new Exception("Type is not a record.");
|
||||
|
||||
className = type.FullName;
|
||||
classId = ResourceTemplate.GetTypeGuid(className);
|
||||
|
||||
#if NETSTANDARD
|
||||
PropertyInfo[] propsInfo = type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
#else
|
||||
PropertyInfo[] propsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
#endif
|
||||
|
||||
bool classIsPublic = type.GetCustomAttribute<PublicAttribute>() != null;
|
||||
|
||||
byte i = 0;
|
||||
|
||||
if (classIsPublic)
|
||||
{
|
||||
foreach (var pi in propsInfo)
|
||||
{
|
||||
var privateAttr = pi.GetCustomAttribute<PrivateAttribute>(true);
|
||||
|
||||
if (privateAttr == null)
|
||||
continue;
|
||||
|
||||
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
|
||||
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
|
||||
|
||||
var pt = new PropertyTemplate(this, i++, pi.Name, TemplateDataType.FromType(pi.PropertyType));
|
||||
|
||||
if (storageAttr != null)
|
||||
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
||||
|
||||
if (annotationAttr != null)
|
||||
pt.ReadExpansion = annotationAttr.Annotation;
|
||||
else
|
||||
pt.ReadExpansion = pi.PropertyType.Name;
|
||||
|
||||
pt.PropertyInfo = pi;
|
||||
//pt.Serilize = publicAttr.Serialize;
|
||||
properties.Add(pt);
|
||||
members.Add(pt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var pi in propsInfo)
|
||||
{
|
||||
var publicAttr = pi.GetCustomAttribute<PublicAttribute>(true);
|
||||
|
||||
if (publicAttr == null)
|
||||
continue;
|
||||
|
||||
|
||||
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
|
||||
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
|
||||
var valueType = TemplateDataType.FromType(pi.PropertyType);
|
||||
|
||||
var pt = new PropertyTemplate(this, i++, pi.Name, valueType);//, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
|
||||
if (storageAttr != null)
|
||||
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
||||
|
||||
if (annotationAttr != null)
|
||||
pt.ReadExpansion = annotationAttr.Annotation;
|
||||
else
|
||||
pt.ReadExpansion = pi.PropertyType.Name;
|
||||
|
||||
pt.PropertyInfo = pi;
|
||||
//pt.Serilize = publicAttr.Serialize;
|
||||
properties.Add(pt);
|
||||
members.Add(pt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// bake it binarily
|
||||
var b = new BinaryList();
|
||||
b.AddGuid(classId)
|
||||
.AddUInt8((byte)className.Length)
|
||||
.AddString(className)
|
||||
.AddInt32(version)
|
||||
.AddUInt16((ushort)members.Count);
|
||||
|
||||
|
||||
foreach (var pt in properties)
|
||||
b.AddUInt8Array(pt.Compose());
|
||||
|
||||
content = b.ToArray();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ namespace Esiur.Resource.Template
|
||||
{
|
||||
public DataType Type { get; set; }
|
||||
//public string TypeName { get; set; }
|
||||
public ResourceTemplate TypeTemplate => TypeGuid == null ? null : Warehouse.GetTemplateByClassId((Guid)TypeGuid);
|
||||
public TypeTemplate TypeTemplate => TypeGuid == null ? null : Warehouse.GetTemplateByClassId((Guid)TypeGuid);
|
||||
|
||||
public Guid? TypeGuid { get; set; }
|
||||
//public TemplateDataType(DataType type, string typeName)
|
||||
@ -49,6 +49,7 @@ namespace Esiur.Resource.Template
|
||||
_ when t == typeof(string) => DataType.String,
|
||||
_ when t == typeof(DateTime) => DataType.DateTime,
|
||||
_ when t == typeof(IResource) => DataType.Void, // Dynamic resource (unspecified type)
|
||||
_ when t == typeof(IRecord) => DataType.Void, // Dynamic record (unspecified type)
|
||||
_ when typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => DataType.Structure,
|
||||
_ when Codec.ImplementsInterface(t, typeof(IResource)) => DataType.Resource,
|
||||
_ when Codec.ImplementsInterface(t, typeof(IRecord)) => DataType.Record,
|
||||
@ -59,7 +60,7 @@ namespace Esiur.Resource.Template
|
||||
Guid? typeGuid = null;
|
||||
|
||||
if (dt == DataType.Resource || dt == DataType.Record)
|
||||
typeGuid = ResourceTemplate.GetTypeGuid(t);
|
||||
typeGuid = TypeTemplate.GetTypeGuid(t);
|
||||
|
||||
if (type.IsArray)
|
||||
dt = (DataType)((byte)dt | 0x80);
|
||||
|
@ -6,7 +6,9 @@ namespace Esiur.Resource.Template
|
||||
{
|
||||
public enum TemplateType:byte
|
||||
{
|
||||
Unspecified,
|
||||
Resource,
|
||||
Record,
|
||||
Wrapper,
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ namespace Esiur.Resource.Template
|
||||
// Record
|
||||
//}
|
||||
|
||||
public class ResourceTemplate
|
||||
public class TypeTemplate
|
||||
{
|
||||
|
||||
protected Guid classId;
|
||||
@ -44,7 +44,7 @@ namespace Esiur.Resource.Template
|
||||
public TemplateType Type => templateType;
|
||||
|
||||
|
||||
public Type ResourceType { get; set; }
|
||||
public Type DefinedType { get; set; }
|
||||
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ namespace Esiur.Resource.Template
|
||||
|
||||
|
||||
|
||||
public ResourceTemplate()
|
||||
public TypeTemplate()
|
||||
{
|
||||
|
||||
}
|
||||
@ -171,18 +171,18 @@ namespace Esiur.Resource.Template
|
||||
|
||||
|
||||
|
||||
public static ResourceTemplate[] GetDependencies(ResourceTemplate template)
|
||||
public static TypeTemplate[] GetDependencies(TypeTemplate template)
|
||||
{
|
||||
|
||||
var list = new List<ResourceTemplate>();
|
||||
var list = new List<TypeTemplate>();
|
||||
|
||||
list.Add(template);
|
||||
|
||||
Action<ResourceTemplate, List<ResourceTemplate>> getDependenciesFunc = null;
|
||||
Action<TypeTemplate, List<TypeTemplate>> getDependenciesFunc = null;
|
||||
|
||||
getDependenciesFunc = (ResourceTemplate tmp, List<ResourceTemplate> bag) =>
|
||||
getDependenciesFunc = (TypeTemplate tmp, List<TypeTemplate> bag) =>
|
||||
{
|
||||
if (template.ResourceType == null)
|
||||
if (template.DefinedType == null)
|
||||
return;
|
||||
|
||||
// functions
|
||||
@ -267,14 +267,16 @@ namespace Esiur.Resource.Template
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public ResourceTemplate(Type type)
|
||||
public TypeTemplate(Type type, bool addToWarehouse = false)
|
||||
{
|
||||
if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
||||
templateType = TemplateType.Record;
|
||||
if (Codec.InheritsClass(type, typeof(DistributedResource)))
|
||||
templateType = TemplateType.Wrapper;
|
||||
else if (Codec.ImplementsInterface(type, typeof(IResource)))
|
||||
templateType = TemplateType.Resource;
|
||||
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
||||
templateType = TemplateType.Record;
|
||||
else
|
||||
throw new Exception("Type is neither a resource nor a record.");
|
||||
throw new Exception("Type must implement IResource, IRecord or inherit from DistributedResource.");
|
||||
|
||||
//if (isRecord && isResource)
|
||||
// throw new Exception("Type can't have both IResource and IRecord interfaces");
|
||||
@ -284,7 +286,7 @@ namespace Esiur.Resource.Template
|
||||
|
||||
type = ResourceProxy.GetBaseType(type);
|
||||
|
||||
ResourceType = type;
|
||||
DefinedType = type;
|
||||
|
||||
className = type.FullName;
|
||||
|
||||
@ -293,6 +295,9 @@ namespace Esiur.Resource.Template
|
||||
// set guid
|
||||
classId = GetTypeGuid(className);
|
||||
|
||||
if (addToWarehouse)
|
||||
Warehouse.PutTemplate(this);
|
||||
|
||||
#if NETSTANDARD
|
||||
PropertyInfo[] propsInfo = type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
|
||||
EventInfo[] eventsInfo = type.GetTypeInfo().GetEvents(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
|
||||
@ -395,8 +400,7 @@ namespace Esiur.Resource.Template
|
||||
Name = x.Name,
|
||||
Type = TemplateDataType.FromType(x.ParameterType),
|
||||
ParameterInfo = x
|
||||
})
|
||||
.ToArray();
|
||||
}).ToArray();
|
||||
|
||||
var ft = new FunctionTemplate(this, i++, mi.Name, arguments, returnType);// mi.ReturnType == typeof(void));
|
||||
|
||||
@ -546,13 +550,13 @@ namespace Esiur.Resource.Template
|
||||
|
||||
}
|
||||
|
||||
public static ResourceTemplate Parse(byte[] data)
|
||||
public static TypeTemplate Parse(byte[] data)
|
||||
{
|
||||
return Parse(data, 0, (uint)data.Length);
|
||||
}
|
||||
|
||||
|
||||
public static ResourceTemplate Parse(byte[] data, uint offset, uint contentLength)
|
||||
public static TypeTemplate Parse(byte[] data, uint offset, uint contentLength)
|
||||
{
|
||||
|
||||
uint ends = offset + contentLength;
|
||||
@ -561,7 +565,7 @@ namespace Esiur.Resource.Template
|
||||
|
||||
// start parsing...
|
||||
|
||||
var od = new ResourceTemplate();
|
||||
var od = new TypeTemplate();
|
||||
od.content = data.Clip(offset, contentLength);
|
||||
|
||||
od.templateType = (TemplateType)data[offset++];
|
@ -53,8 +53,17 @@ namespace Esiur.Resource
|
||||
|
||||
static uint resourceCounter = 0;
|
||||
|
||||
static KeyList<Guid, ResourceTemplate> templates = new KeyList<Guid, ResourceTemplate>();
|
||||
static KeyList<Guid, ResourceTemplate> wrapperTemplates = new KeyList<Guid, ResourceTemplate>();
|
||||
//static KeyList<Guid, TypeTemplate> templates = new KeyList<Guid, TypeTemplate>();
|
||||
//static KeyList<Guid, TypeTemplate> wrapperTemplates = new KeyList<Guid, TypeTemplate>();
|
||||
|
||||
static KeyList<TemplateType, KeyList<Guid, TypeTemplate>> templates
|
||||
= new KeyList<TemplateType, KeyList<Guid, TypeTemplate>>()
|
||||
{
|
||||
[TemplateType.Unspecified] = new KeyList<Guid, TypeTemplate>(),
|
||||
[TemplateType.Resource] = new KeyList<Guid, TypeTemplate>(),
|
||||
[TemplateType.Record] = new KeyList<Guid, TypeTemplate>(),
|
||||
[TemplateType.Wrapper] = new KeyList<Guid, TypeTemplate>(),
|
||||
};
|
||||
|
||||
static bool warehouseIsOpen = false;
|
||||
|
||||
@ -124,13 +133,13 @@ namespace Esiur.Resource
|
||||
var resourceTypes = (Type[])generatedType.GetProperty("Resources").GetValue(null);
|
||||
foreach (var t in resourceTypes)
|
||||
{
|
||||
PutTemplate(new ResourceTemplate(t), true);
|
||||
PutTemplate(new TypeTemplate(t));
|
||||
}
|
||||
|
||||
var recordTypes = (Type[])generatedType.GetProperty("Records").GetValue(null);
|
||||
foreach (var t in recordTypes)
|
||||
{
|
||||
PutTemplate(new ResourceTemplate(t));
|
||||
PutTemplate(new TypeTemplate(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -519,7 +528,7 @@ namespace Esiur.Resource
|
||||
/// <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 static async AsyncReply<T> Put<T>(string name, T resource, IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T:IResource
|
||||
public static async AsyncReply<T> Put<T>(string name, T resource, IStore store = null, IResource parent = null, TypeTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T:IResource
|
||||
{
|
||||
if (resource.Instance != null)
|
||||
throw new Exception("Resource has a store.");
|
||||
@ -737,15 +746,9 @@ namespace Esiur.Resource
|
||||
/// Put a resource template in the templates warehouse.
|
||||
/// </summary>
|
||||
/// <param name="template">Resource template.</param>
|
||||
public static void PutTemplate(ResourceTemplate template, bool wrapper = false)
|
||||
public static void PutTemplate(TypeTemplate template)
|
||||
{
|
||||
if (wrapper)
|
||||
{
|
||||
if (!wrapperTemplates.ContainsKey(template.ClassId))
|
||||
wrapperTemplates.Add(template.ClassId, template);
|
||||
}
|
||||
else if (!templates.ContainsKey(template.ClassId))
|
||||
templates.Add(template.ClassId, template);
|
||||
templates[template.Type][template.ClassId] = template;
|
||||
}
|
||||
|
||||
|
||||
@ -754,11 +757,18 @@ namespace Esiur.Resource
|
||||
/// </summary>
|
||||
/// <param name="type">.Net type.</param>
|
||||
/// <returns>Resource template.</returns>
|
||||
public static ResourceTemplate GetTemplateByType(Type type)
|
||||
public static TypeTemplate GetTemplateByType(Type type)
|
||||
{
|
||||
|
||||
if (!(Codec.ImplementsInterface(type, typeof(IResource))
|
||||
|| Codec.ImplementsInterface(type, typeof(IRecord))))
|
||||
TemplateType templateType = TemplateType.Unspecified;
|
||||
|
||||
if (Codec.InheritsClass(type, typeof(DistributedResource)))
|
||||
templateType = TemplateType.Wrapper;
|
||||
if (Codec.ImplementsInterface(type, typeof(IResource)))
|
||||
templateType = TemplateType.Resource;
|
||||
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
||||
templateType = TemplateType.Record;
|
||||
else
|
||||
return null;
|
||||
|
||||
var baseType = ResourceProxy.GetBaseType(type);
|
||||
@ -767,13 +777,11 @@ namespace Esiur.Resource
|
||||
|| baseType == typeof(IRecord))
|
||||
return null;
|
||||
|
||||
// loaded ?
|
||||
foreach (var t in templates.Values)
|
||||
if (t.ClassName == baseType.FullName)
|
||||
return t;
|
||||
var template = templates[templateType].Values.FirstOrDefault(x => x.DefinedType == type);
|
||||
|
||||
var template = new ResourceTemplate(baseType);
|
||||
templates.Add(template.ClassId, template);
|
||||
// loaded ?
|
||||
if (template == null)
|
||||
template = new TypeTemplate(baseType, true);
|
||||
|
||||
return template;
|
||||
}
|
||||
@ -783,17 +791,26 @@ namespace Esiur.Resource
|
||||
/// </summary>
|
||||
/// <param name="classId">Class Id.</param>
|
||||
/// <returns>Resource template.</returns>
|
||||
public static ResourceTemplate GetTemplateByClassId(Guid classId, bool wrapper = false)
|
||||
public static TypeTemplate GetTemplateByClassId(Guid classId, TemplateType templateType = TemplateType.Unspecified)
|
||||
{
|
||||
if (wrapper)
|
||||
if (templateType == TemplateType.Unspecified)
|
||||
{
|
||||
if (wrapperTemplates.ContainsKey(classId))
|
||||
return wrapperTemplates[classId];
|
||||
}
|
||||
else if (templates.ContainsKey(classId))
|
||||
return templates[classId];
|
||||
// look in resources
|
||||
var template = templates[TemplateType.Resource][classId];
|
||||
if (template != null)
|
||||
return template;
|
||||
|
||||
return null;
|
||||
// look in records
|
||||
template = templates[TemplateType.Record][classId];
|
||||
if (template != null)
|
||||
return template;
|
||||
|
||||
// look in wrappers
|
||||
template = templates[TemplateType.Wrapper][classId];
|
||||
return template;
|
||||
}
|
||||
else
|
||||
return templates[templateType][classId];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -801,13 +818,28 @@ namespace Esiur.Resource
|
||||
/// </summary>
|
||||
/// <param name="className">Class name.</param>
|
||||
/// <returns>Resource template.</returns>
|
||||
public static AsyncReply<ResourceTemplate> GetTemplateByClassName(string className)
|
||||
public static TypeTemplate GetTemplateByClassName(string className, TemplateType templateType = TemplateType.Unspecified)
|
||||
{
|
||||
foreach (var t in templates.Values)
|
||||
if (t.ClassName == className)
|
||||
return new AsyncReply<ResourceTemplate>(t);
|
||||
if (templateType == TemplateType.Unspecified)
|
||||
{
|
||||
// look in resources
|
||||
var template = templates[TemplateType.Resource].Values.FirstOrDefault(x => x.ClassName == className);
|
||||
if (template != null)
|
||||
return template;
|
||||
|
||||
return null;
|
||||
// look in records
|
||||
template = templates[TemplateType.Record].Values.FirstOrDefault(x => x.ClassName == className);
|
||||
if (template != null)
|
||||
return template;
|
||||
|
||||
// look in wrappers
|
||||
template = templates[TemplateType.Wrapper].Values.FirstOrDefault(x => x.ClassName == className);
|
||||
return template;
|
||||
}
|
||||
else
|
||||
{
|
||||
return templates[templateType].Values.FirstOrDefault(x => x.ClassName == className);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Remove(IResource resource)
|
||||
|
Loading…
x
Reference in New Issue
Block a user