mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-05-06 11:32:59 +00:00
ResourceTemplate 2.0
This commit is contained in:
parent
c8683e17e9
commit
82cbe3b01c
@ -52,10 +52,10 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
|
|
||||||
[Public]
|
[Public]
|
||||||
public event ResourceEventHanlder ResourceAdded;
|
public event ResourceEventHanlder<IResource> ResourceAdded;
|
||||||
|
|
||||||
[Public]
|
[Public]
|
||||||
public event ResourceEventHanlder ResourceRemoved;
|
public event ResourceEventHanlder<IResource> ResourceRemoved;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
@ -225,7 +225,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
var doc = value.AsBsonDocument;
|
var doc = value.AsBsonDocument;
|
||||||
if (doc["type"] == 0)
|
if (doc["type"] == 0)
|
||||||
{
|
{
|
||||||
return Warehouse.Get(doc["link"].AsString);
|
return Warehouse.Get<IResource>(doc["link"].AsString);
|
||||||
} // structure
|
} // structure
|
||||||
else if (doc["type"] == 1)
|
else if (doc["type"] == 1)
|
||||||
{
|
{
|
||||||
@ -383,7 +383,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
foreach (var pt in template.Properties)
|
foreach (var pt in template.Properties)
|
||||||
{
|
{
|
||||||
var rt = pt.Info.GetValue(resource, null);
|
var rt = pt.PropertyInfo.GetValue(resource, null);
|
||||||
|
|
||||||
values.Add(pt.Name,
|
values.Add(pt.Name,
|
||||||
new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) },
|
new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) },
|
||||||
@ -612,7 +612,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
var pi = resource.GetType().GetProperty(pt.Name);
|
var pi = resource.GetType().GetProperty(pt.Name);
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
var rt = pt.Info.GetValue(resource, null);
|
var rt = pt.PropertyInfo.GetValue(resource, null);
|
||||||
|
|
||||||
values.Add(pt.Name,
|
values.Add(pt.Name,
|
||||||
new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) },
|
new BsonDocument { { "age", BsonValue.Create(resource.Instance.GetAge(pt.Index)) },
|
||||||
@ -841,7 +841,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
foreach (var child in children)
|
foreach (var child in children)
|
||||||
{
|
{
|
||||||
var r = Warehouse.Get(child);
|
var r = Warehouse.Get<T>(child);
|
||||||
if (r is AsyncReply<T>)
|
if (r is AsyncReply<T>)
|
||||||
rt.Add(r);// (AsyncReply<T>)r);
|
rt.Add(r);// (AsyncReply<T>)r);
|
||||||
}
|
}
|
||||||
@ -873,7 +873,7 @@ namespace Esiur.Stores.MongoDB
|
|||||||
|
|
||||||
foreach (var parent in parents)
|
foreach (var parent in parents)
|
||||||
{
|
{
|
||||||
var r = Warehouse.Get(parent);
|
var r = Warehouse.Get<T>(parent);
|
||||||
if (r is AsyncReply<T>)
|
if (r is AsyncReply<T>)
|
||||||
rt.Add(r);// (AsyncReply<T>)r);
|
rt.Add(r);// (AsyncReply<T>)r);
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,8 @@ namespace Esiur.Core
|
|||||||
if (Debug)
|
if (Debug)
|
||||||
Console.WriteLine($"AsyncReply: {Id} Wait ended");
|
Console.WriteLine($"AsyncReply: {Id} Wait ended");
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
throw exception;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ namespace Esiur.Data
|
|||||||
|
|
||||||
foreach (var pt in resource.Instance.Template.Properties)
|
foreach (var pt in resource.Instance.Template.Properties)
|
||||||
{
|
{
|
||||||
var rt = pt.Info.GetValue(resource, null);
|
var rt = pt.PropertyInfo.GetValue(resource, null);
|
||||||
if (rt is DistributedPropertyContext)
|
if (rt is DistributedPropertyContext)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
<PackageLicenseUrl>https://github.com/Esiur/Esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/Esiur/Esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
|
||||||
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Version>1.7.1</Version>
|
<Version>1.8.1</Version>
|
||||||
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
|
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
|
||||||
<Authors>Ahmed Kh. Zamil</Authors>
|
<Authors>Ahmed Kh. Zamil</Authors>
|
||||||
<AssemblyVersion>1.7.1</AssemblyVersion>
|
<AssemblyVersion>1.8.1.0</AssemblyVersion>
|
||||||
<Company>Esiur Foundation</Company>
|
<Company>Esiur Foundation</Company>
|
||||||
<FileVersion>1.7.1</FileVersion>
|
<FileVersion>1.8.1.0</FileVersion>
|
||||||
<AssemblyName>Esiur</AssemblyName>
|
<AssemblyName>Esiur</AssemblyName>
|
||||||
<RootNamespace>Esiur</RootNamespace>
|
<RootNamespace>Esiur</RootNamespace>
|
||||||
<PackageId>Esiur</PackageId>
|
<PackageId>Esiur</PackageId>
|
||||||
@ -57,6 +57,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.9.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.9.0" />
|
||||||
|
<PackageReference Include="System.Collections" Version="4.3.0" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Diagnostics.StackTrace" Version="4.3.0" />
|
<PackageReference Include="System.Diagnostics.StackTrace" Version="4.3.0" />
|
||||||
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
|
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
|
||||||
@ -65,7 +66,7 @@
|
|||||||
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
|
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
|
||||||
<PackageReference Include="System.Net.Security" Version="4.3.2" />
|
<PackageReference Include="System.Net.Security" Version="4.3.2" />
|
||||||
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
|
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
|
||||||
<PackageReference Include="System.Text.Json" Version="5.0.2" />
|
<PackageReference Include="System.Text.Json" Version="5.0.2" GeneratePathProperty="true" />
|
||||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
|
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
|
||||||
@ -76,6 +77,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||||
|
<!-- Package the Newtonsoft.Json dependency alongside the generator assembly -->
|
||||||
|
<None Include="$(PkgSystem_Text_Json)\lib\netstandard2.0\*.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -470,6 +470,10 @@ namespace Esiur.Net.IIP
|
|||||||
IIPRequestInquireResourceHistory(packet.CallbackId, packet.ResourceId, packet.FromDate, packet.ToDate);
|
IIPRequestInquireResourceHistory(packet.CallbackId, packet.ResourceId, packet.FromDate, packet.ToDate);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IIPPacketAction.LinkTemplates:
|
||||||
|
IIPRequestLinkTemplates(packet.CallbackId, packet.ResourceLink);
|
||||||
|
break;
|
||||||
|
|
||||||
// Invoke
|
// Invoke
|
||||||
case IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments:
|
case IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments:
|
||||||
IIPRequestInvokeFunctionArrayArguments(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
|
IIPRequestInvokeFunctionArrayArguments(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
|
||||||
@ -559,6 +563,7 @@ namespace Esiur.Net.IIP
|
|||||||
case IIPPacketAction.ResourceChildren:
|
case IIPPacketAction.ResourceChildren:
|
||||||
case IIPPacketAction.ResourceParents:
|
case IIPPacketAction.ResourceParents:
|
||||||
case IIPPacketAction.ResourceHistory:
|
case IIPPacketAction.ResourceHistory:
|
||||||
|
case IIPPacketAction.LinkTemplates:
|
||||||
IIPReply(packet.CallbackId, packet.Content);
|
IIPReply(packet.CallbackId, packet.Content);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -699,10 +704,12 @@ namespace Esiur.Net.IIP
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Console.WriteLine("User not found");
|
//Console.WriteLine("User not found");
|
||||||
SendParams().AddUInt8(0xc0)
|
SendParams()
|
||||||
|
.AddUInt8(0xc0)
|
||||||
.AddUInt8((byte)ExceptionCode.UserOrTokenNotFound)
|
.AddUInt8((byte)ExceptionCode.UserOrTokenNotFound)
|
||||||
.AddUInt16(15)
|
.AddUInt16(15)
|
||||||
.AddString("Token not found").Done();
|
.AddString("Token not found")
|
||||||
|
.Done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -710,12 +717,49 @@ namespace Esiur.Net.IIP
|
|||||||
{
|
{
|
||||||
var errMsg = DC.ToBytes(ex.Message);
|
var errMsg = DC.ToBytes(ex.Message);
|
||||||
|
|
||||||
|
SendParams()
|
||||||
|
.AddUInt8(0xc0)
|
||||||
|
.AddUInt8((byte)ExceptionCode.GeneralFailure)
|
||||||
|
.AddUInt16((ushort)errMsg.Length)
|
||||||
|
.AddUInt8Array(errMsg)
|
||||||
|
.Done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (authPacket.RemoteMethod == AuthenticationMethod.None && authPacket.LocalMethod == AuthenticationMethod.None)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check if guests are allowed
|
||||||
|
if (Server.Membership.GuestsAllowed)
|
||||||
|
{
|
||||||
|
session.RemoteAuthentication.Username = "g-" + Global.GenerateCode();
|
||||||
|
session.RemoteAuthentication.Domain = authPacket.Domain;
|
||||||
|
readyToEstablish = true;
|
||||||
|
SendParams()
|
||||||
|
.AddUInt8(0x80)
|
||||||
|
.Done();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendParams()
|
||||||
|
.AddUInt8(0xc0)
|
||||||
|
.AddUInt8((byte)ExceptionCode.AccessDenied)
|
||||||
|
.AddUInt16(18)
|
||||||
|
.AddString("Guests not allowed")
|
||||||
|
.Done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var errMsg = DC.ToBytes(ex.Message);
|
||||||
|
|
||||||
SendParams().AddUInt8(0xc0)
|
SendParams().AddUInt8(0xc0)
|
||||||
.AddUInt8((byte)ExceptionCode.GeneralFailure)
|
.AddUInt8((byte)ExceptionCode.GeneralFailure)
|
||||||
.AddUInt16((ushort)errMsg.Length)
|
.AddUInt16((ushort)errMsg.Length)
|
||||||
.AddUInt8Array(errMsg).Done();
|
.AddUInt8Array(errMsg).Done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Action)
|
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Action)
|
||||||
{
|
{
|
||||||
@ -831,6 +875,16 @@ namespace Esiur.Net.IIP
|
|||||||
else if (session.LocalAuthentication.Type == AuthenticationType.Client)
|
else if (session.LocalAuthentication.Type == AuthenticationType.Client)
|
||||||
{
|
{
|
||||||
if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Acknowledge)
|
if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Acknowledge)
|
||||||
|
{
|
||||||
|
if (authPacket.LocalMethod == AuthenticationMethod.None)
|
||||||
|
{
|
||||||
|
SendParams()
|
||||||
|
.AddUInt8(0x20)
|
||||||
|
.AddUInt16(0)
|
||||||
|
.Done();
|
||||||
|
}
|
||||||
|
else if (authPacket.LocalMethod == AuthenticationMethod.Credentials
|
||||||
|
|| authPacket.LocalMethod == AuthenticationMethod.Token)
|
||||||
{
|
{
|
||||||
remoteNonce = authPacket.RemoteNonce;
|
remoteNonce = authPacket.RemoteNonce;
|
||||||
|
|
||||||
@ -847,7 +901,7 @@ namespace Esiur.Net.IIP
|
|||||||
.AddUInt8(0)
|
.AddUInt8(0)
|
||||||
.AddUInt8Array(localHash)
|
.AddUInt8Array(localHash)
|
||||||
.Done();
|
.Done();
|
||||||
|
}
|
||||||
//SendParams((byte)0, localHash);
|
//SendParams((byte)0, localHash);
|
||||||
}
|
}
|
||||||
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Action)
|
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Action)
|
||||||
@ -867,7 +921,6 @@ namespace Esiur.Net.IIP
|
|||||||
if (remoteHash.SequenceEqual(authPacket.Hash))
|
if (remoteHash.SequenceEqual(authPacket.Hash))
|
||||||
{
|
{
|
||||||
// send establish request
|
// send establish request
|
||||||
//SendParams((byte)0x20, (ushort)0);
|
|
||||||
SendParams()
|
SendParams()
|
||||||
.AddUInt8(0x20)
|
.AddUInt8(0x20)
|
||||||
.AddUInt16(0)
|
.AddUInt16(0)
|
||||||
@ -981,32 +1034,29 @@ namespace Esiur.Net.IIP
|
|||||||
{
|
{
|
||||||
if (trigger == ResourceTrigger.Open)
|
if (trigger == ResourceTrigger.Open)
|
||||||
{
|
{
|
||||||
|
if (this.Server != null)
|
||||||
|
return new AsyncReply<bool>(true);
|
||||||
|
|
||||||
|
var host = Instance.Name.Split(':');
|
||||||
|
|
||||||
|
var address = host[0];
|
||||||
|
var port = ushort.Parse(host[1]);
|
||||||
|
// assign domain from hostname if not provided
|
||||||
|
var domain = Domain != null ? Domain : address;
|
||||||
|
|
||||||
if (Username != null // Instance.Attributes.ContainsKey("username")
|
if (Username != null // Instance.Attributes.ContainsKey("username")
|
||||||
&& Password != null)/// Instance.Attributes.ContainsKey("password"))
|
&& Password != null)/// Instance.Attributes.ContainsKey("password"))
|
||||||
{
|
{
|
||||||
// assign domain from hostname if not provided
|
|
||||||
|
|
||||||
var host = Instance.Name.Split(':');
|
|
||||||
|
|
||||||
var address = host[0];
|
|
||||||
var port = ushort.Parse(host[1]);
|
|
||||||
|
|
||||||
var domain = Domain != null ? Domain : address;
|
|
||||||
|
|
||||||
|
|
||||||
return Connect(AuthenticationMethod.Credentials, null, address, port, Username, 0, DC.ToBytes(Password), domain);
|
return Connect(AuthenticationMethod.Credentials, null, address, port, Username, 0, DC.ToBytes(Password), domain);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (Token != null)
|
else if (Token != null)
|
||||||
{
|
{
|
||||||
var host = Instance.Name.Split(':');
|
|
||||||
|
|
||||||
var address = host[0];
|
|
||||||
var port = ushort.Parse(host[1]);
|
|
||||||
|
|
||||||
var domain = Domain != null ? Domain : address;
|
|
||||||
|
|
||||||
return Connect(AuthenticationMethod.Token, null, address, port, null, TokenIndex, DC.ToBytes(Token), domain);
|
return Connect(AuthenticationMethod.Token, null, address, port, null, TokenIndex, DC.ToBytes(Token), domain);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
return Connect(AuthenticationMethod.None, null, address, port, null, 0, null, domain);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1077,6 +1077,50 @@ namespace Esiur.Net.IIP
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IIPRequestLinkTemplates(uint callback, string resourceLink)
|
||||||
|
{
|
||||||
|
Console.WriteLine("IIPRequestLinkTemplates " + DateTime.UtcNow);
|
||||||
|
Action<IResource[]> queryCallback = (r) =>
|
||||||
|
{
|
||||||
|
if (r == null)
|
||||||
|
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var list = r.Where(x => x.Instance.Applicable(session, ActionType.ViewTemplate, null) != Ruling.Denied).ToArray();
|
||||||
|
|
||||||
|
if (list.Length == 0)
|
||||||
|
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get all templates related to this resource
|
||||||
|
|
||||||
|
var msg = new BinaryList();
|
||||||
|
|
||||||
|
var templates = new List<ResourceTemplate>();
|
||||||
|
foreach (var resource in list)
|
||||||
|
templates.AddRange(ResourceTemplate.GetRuntimeTypes(resource.Instance.Template).Where(x => !templates.Contains(x)));
|
||||||
|
|
||||||
|
foreach(var t in templates)
|
||||||
|
{
|
||||||
|
msg.AddInt32(t.Content.Length)
|
||||||
|
.AddUInt8Array(t.Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// digggg
|
||||||
|
SendReply(IIPPacket.IIPPacketAction.LinkTemplates, callback)
|
||||||
|
.AddInt32(msg.Length)
|
||||||
|
.AddUInt8Array(msg.ToArray())
|
||||||
|
.Done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Server?.EntryPoint != null)
|
||||||
|
Server.EntryPoint.Query(resourceLink, this).Then(queryCallback);
|
||||||
|
else
|
||||||
|
Warehouse.Query(resourceLink).Then(queryCallback);
|
||||||
|
}
|
||||||
|
|
||||||
void IIPRequestTemplateFromClassName(uint callback, string className)
|
void IIPRequestTemplateFromClassName(uint callback, string className)
|
||||||
{
|
{
|
||||||
Warehouse.GetTemplate(className).Then((t) =>
|
Warehouse.GetTemplate(className).Then((t) =>
|
||||||
@ -1096,8 +1140,8 @@ namespace Esiur.Net.IIP
|
|||||||
|
|
||||||
void IIPRequestTemplateFromClassId(uint callback, Guid classId)
|
void IIPRequestTemplateFromClassId(uint callback, Guid classId)
|
||||||
{
|
{
|
||||||
Warehouse.GetTemplate(classId).Then((t) =>
|
var t = Warehouse.GetTemplate(classId);
|
||||||
{
|
|
||||||
if (t != null)
|
if (t != null)
|
||||||
SendReply(IIPPacket.IIPPacketAction.TemplateFromClassId, callback)
|
SendReply(IIPPacket.IIPPacketAction.TemplateFromClassId, callback)
|
||||||
.AddInt32(t.Content.Length)
|
.AddInt32(t.Content.Length)
|
||||||
@ -1108,7 +1152,6 @@ namespace Esiur.Net.IIP
|
|||||||
// reply failed
|
// reply failed
|
||||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
|
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.TemplateNotFound);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1791,7 +1834,7 @@ namespace Esiur.Net.IIP
|
|||||||
var pi = r.GetType().GetProperty(pt.Name);
|
var pi = r.GetType().GetProperty(pt.Name);
|
||||||
#endif*/
|
#endif*/
|
||||||
|
|
||||||
var pi = pt.Info;
|
var pi = pt.PropertyInfo;
|
||||||
|
|
||||||
if (pi != null)
|
if (pi != null)
|
||||||
{
|
{
|
||||||
@ -2091,6 +2134,43 @@ namespace Esiur.Net.IIP
|
|||||||
return new AsyncReply<IResource>(null);
|
return new AsyncReply<IResource>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AsyncReply<ResourceTemplate[]> GetLinkTemplates(string link)
|
||||||
|
{
|
||||||
|
var reply = new AsyncReply<ResourceTemplate[]>();
|
||||||
|
|
||||||
|
var l = DC.ToBytes(link);
|
||||||
|
|
||||||
|
SendRequest(IIPPacket.IIPPacketAction.LinkTemplates)
|
||||||
|
.AddUInt16((ushort)l.Length)
|
||||||
|
.AddUInt8Array(l)
|
||||||
|
.Done()
|
||||||
|
.Then((rt) =>
|
||||||
|
{
|
||||||
|
|
||||||
|
var templates = new List<ResourceTemplate>();
|
||||||
|
// parse templates
|
||||||
|
|
||||||
|
var data = (byte[])rt[0];
|
||||||
|
//var offset = 0;
|
||||||
|
for (uint offset = 0; offset < data.Length;)
|
||||||
|
{
|
||||||
|
var cs = data.GetUInt32(offset);
|
||||||
|
offset += 4;
|
||||||
|
templates.Add(ResourceTemplate.Parse(data, offset, cs));
|
||||||
|
offset += cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.Trigger(templates.ToArray());
|
||||||
|
|
||||||
|
}).Error((ex) =>
|
||||||
|
{
|
||||||
|
reply.TriggerError(ex);
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fetch a resource from the other end
|
/// Fetch a resource from the other end
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -2125,7 +2205,19 @@ namespace Esiur.Net.IIP
|
|||||||
.Then((rt) =>
|
.Then((rt) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
var dr = resource ?? new DistributedResource(this, id, (ulong)rt[1], (string)rt[2]);
|
DistributedResource dr;
|
||||||
|
|
||||||
|
if (resource == null)
|
||||||
|
{
|
||||||
|
var template = Warehouse.GetTemplate((Guid)rt[0]);
|
||||||
|
if (template?.RuntimeType != null)
|
||||||
|
dr = Activator.CreateInstance(template.RuntimeType, this, id, (ulong)rt[1], (string)rt[2]) as DistributedResource;
|
||||||
|
else
|
||||||
|
dr = new DistributedResource(this, id, (ulong)rt[1], (string)rt[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dr = resource;
|
||||||
|
|
||||||
|
|
||||||
GetTemplate((Guid)rt[0]).Then((tmp) =>
|
GetTemplate((Guid)rt[0]).Then((tmp) =>
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ namespace Esiur.Net.IIP
|
|||||||
string link;
|
string link;
|
||||||
//ulong age;
|
//ulong age;
|
||||||
//ulong[] ages;
|
//ulong[] ages;
|
||||||
object[] properties;
|
protected object[] properties;
|
||||||
internal List<DistributedResource> parents = new List<DistributedResource>();
|
internal List<DistributedResource> parents = new List<DistributedResource>();
|
||||||
internal List<DistributedResource> children = new List<DistributedResource>();
|
internal List<DistributedResource> children = new List<DistributedResource>();
|
||||||
|
|
||||||
@ -210,13 +210,16 @@ namespace Esiur.Net.IIP
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void _EmitEventByIndex(byte index, object args)
|
|
||||||
|
protected internal virtual void _EmitEventByIndex(byte index, object args)
|
||||||
{
|
{
|
||||||
var et = Instance.Template.GetEventTemplateByIndex(index);
|
var et = Instance.Template.GetEventTemplateByIndex(index);
|
||||||
events[index]?.Invoke(this, args);
|
events[index]?.Invoke(this, args);
|
||||||
Instance.EmitResourceEvent(et.Name, args);
|
Instance.EmitResourceEvent(et.Name, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public AsyncReply<object> _InvokeByNamedArguments(byte index, Structure namedArgs)
|
public AsyncReply<object> _InvokeByNamedArguments(byte index, Structure namedArgs)
|
||||||
{
|
{
|
||||||
if (destroyed)
|
if (destroyed)
|
||||||
@ -332,7 +335,7 @@ namespace Esiur.Net.IIP
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">Zero-based property index.</param>
|
/// <param name="index">Zero-based property index.</param>
|
||||||
/// <returns>Value</returns>
|
/// <returns>Value</returns>
|
||||||
internal object _Get(byte index)
|
protected internal object _Get(byte index)
|
||||||
{
|
{
|
||||||
if (index >= properties.Length)
|
if (index >= properties.Length)
|
||||||
return null;
|
return null;
|
||||||
@ -383,7 +386,7 @@ namespace Esiur.Net.IIP
|
|||||||
/// <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>
|
||||||
internal AsyncReply<object> _Set(byte index, object value)
|
protected internal AsyncReply<object> _Set(byte index, object value)
|
||||||
{
|
{
|
||||||
if (index >= properties.Length)
|
if (index >= properties.Length)
|
||||||
return null;
|
return null;
|
||||||
|
@ -30,5 +30,5 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Esiur.Net.IIP
|
namespace Esiur.Net.IIP
|
||||||
{
|
{
|
||||||
public delegate void DistributedResourceEvent(DistributedResource sender, object arguments);
|
public delegate void DistributedResourceEvent(DistributedResource sender, object argument);
|
||||||
}
|
}
|
||||||
|
@ -344,11 +344,14 @@ namespace Esiur.Net.Packets
|
|||||||
LocalMethod = (AuthenticationMethod)((data[offset] >> 2) & 0x3);
|
LocalMethod = (AuthenticationMethod)((data[offset] >> 2) & 0x3);
|
||||||
var encrypt = ((data[offset++] & 0x2) == 0x2);
|
var encrypt = ((data[offset++] & 0x2) == 0x2);
|
||||||
|
|
||||||
if (NotEnough(offset, ends, 1))
|
if (RemoteMethod == AuthenticationMethod.None)
|
||||||
return -dataLengthNeeded;
|
{
|
||||||
|
if (LocalMethod == AuthenticationMethod.None)
|
||||||
|
{
|
||||||
if (RemoteMethod == AuthenticationMethod.Credentials
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (RemoteMethod == AuthenticationMethod.Credentials
|
||||||
|| RemoteMethod == AuthenticationMethod.Token)
|
|| RemoteMethod == AuthenticationMethod.Token)
|
||||||
{
|
{
|
||||||
if (LocalMethod == AuthenticationMethod.None)
|
if (LocalMethod == AuthenticationMethod.None)
|
||||||
|
@ -107,6 +107,7 @@ namespace Esiur.Net.Packets
|
|||||||
ResourceHistory,
|
ResourceHistory,
|
||||||
ResourceChildren,
|
ResourceChildren,
|
||||||
ResourceParents,
|
ResourceParents,
|
||||||
|
LinkTemplates,
|
||||||
|
|
||||||
// Request Invoke
|
// Request Invoke
|
||||||
InvokeFunctionArrayArguments = 0x10,
|
InvokeFunctionArrayArguments = 0x10,
|
||||||
@ -484,7 +485,8 @@ namespace Esiur.Net.Packets
|
|||||||
ResourceId = data.GetUInt32(offset);
|
ResourceId = data.GetUInt32(offset);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
}
|
}
|
||||||
else if (Action == IIPPacketAction.QueryLink)
|
else if (Action == IIPPacketAction.QueryLink
|
||||||
|
|| Action == IIPPacketAction.LinkTemplates)
|
||||||
{
|
{
|
||||||
if (NotEnough(offset, ends, 2))
|
if (NotEnough(offset, ends, 2))
|
||||||
return -dataLengthNeeded;
|
return -dataLengthNeeded;
|
||||||
@ -691,6 +693,7 @@ namespace Esiur.Net.Packets
|
|||||||
|| Action == IIPPacketAction.ResourceChildren
|
|| Action == IIPPacketAction.ResourceChildren
|
||||||
|| Action == IIPPacketAction.ResourceParents
|
|| Action == IIPPacketAction.ResourceParents
|
||||||
|| Action == IIPPacketAction.ResourceHistory
|
|| Action == IIPPacketAction.ResourceHistory
|
||||||
|
|| Action == IIPPacketAction.LinkTemplates
|
||||||
// Attribute
|
// Attribute
|
||||||
|| Action == IIPPacketAction.GetAllAttributes
|
|| Action == IIPPacketAction.GetAllAttributes
|
||||||
|| Action == IIPPacketAction.GetAttributes)
|
|| Action == IIPPacketAction.GetAttributes)
|
||||||
|
@ -6,43 +6,247 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Esiur.Net.IIP;
|
||||||
|
using Esiur.Resource;
|
||||||
|
using Esiur.Resource.Template;
|
||||||
|
using Esiur.Data;
|
||||||
|
using System.IO;
|
||||||
|
using Esiur.Core;
|
||||||
|
|
||||||
namespace Esiur.Proxy
|
namespace Esiur.Proxy
|
||||||
{
|
{
|
||||||
[Generator]
|
[Generator]
|
||||||
public class ResourceGenerator : ISourceGenerator
|
public class ResourceGenerator : ISourceGenerator
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
private static Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)");
|
||||||
|
|
||||||
|
private KeyList<string, ResourceTemplate[]> cache = new();
|
||||||
|
// private List<string> inProgress = new();
|
||||||
|
|
||||||
public void Initialize(GeneratorInitializationContext context)
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
{
|
{
|
||||||
// Register receiver
|
// Register receiver
|
||||||
|
|
||||||
context.RegisterForSyntaxNotifications(() => new ResourceGeneratorReceiver());
|
context.RegisterForSyntaxNotifications(() => new ResourceGeneratorReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string GetTypeName(TemplateDataType templateDataType, ResourceTemplate[] templates)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (templateDataType.Type == DataType.Resource)
|
||||||
|
return templates.First(x => x.ClassId == templateDataType.TypeGuid).ClassName;
|
||||||
|
else if (templateDataType.Type == DataType.ResourceArray)
|
||||||
|
return templates.First(x => x.ClassId == templateDataType.TypeGuid).ClassName + "[]";
|
||||||
|
|
||||||
|
var name = templateDataType.Type switch
|
||||||
|
{
|
||||||
|
DataType.Bool => "bool",
|
||||||
|
DataType.BoolArray => "bool[]",
|
||||||
|
DataType.Char => "char",
|
||||||
|
DataType.CharArray => "char[]",
|
||||||
|
DataType.DateTime => "DateTime",
|
||||||
|
DataType.DateTimeArray => "DateTime[]",
|
||||||
|
DataType.Decimal => "decimal",
|
||||||
|
DataType.DecimalArray => "decimal[]",
|
||||||
|
DataType.Float32 => "float",
|
||||||
|
DataType.Float32Array => "float[]",
|
||||||
|
DataType.Float64 => "double",
|
||||||
|
DataType.Float64Array => "double[]",
|
||||||
|
DataType.Int16 => "short",
|
||||||
|
DataType.Int16Array => "short[]",
|
||||||
|
DataType.Int32 => "int",
|
||||||
|
DataType.Int32Array => "int[]",
|
||||||
|
DataType.Int64 => "long",
|
||||||
|
DataType.Int64Array => "long[]",
|
||||||
|
DataType.Int8 => "sbyte",
|
||||||
|
DataType.Int8Array => "sbyte[]",
|
||||||
|
DataType.String => "string",
|
||||||
|
DataType.StringArray => "string[]",
|
||||||
|
DataType.Structure => "Structure",
|
||||||
|
DataType.StructureArray => "Structure[]",
|
||||||
|
DataType.UInt16 => "ushort",
|
||||||
|
DataType.UInt16Array => "ushort[]",
|
||||||
|
DataType.UInt32 => "uint",
|
||||||
|
DataType.UInt32Array => "uint[]",
|
||||||
|
DataType.UInt64 => "ulong",
|
||||||
|
DataType.UInt64Array => "ulong[]",
|
||||||
|
DataType.UInt8 => "byte",
|
||||||
|
DataType.UInt8Array => "byte[]",
|
||||||
|
DataType.VarArray => "object[]",
|
||||||
|
DataType.Void => "object",
|
||||||
|
_ => "object"
|
||||||
|
};
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportError(GeneratorExecutionContext context, string title, string msg, string category)
|
||||||
|
{
|
||||||
|
context.ReportDiagnostic(Diagnostic.Create(new DiagnosticDescriptor("MySG001", title, msg, category, DiagnosticSeverity.Error, true), Location.None));
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateClass(ResourceTemplate template, ResourceTemplate[] templates)
|
||||||
|
{
|
||||||
|
var cls = template.ClassName.Split('.');
|
||||||
|
|
||||||
|
var nameSpace = string.Join(".", cls.Take(cls.Length - 1));
|
||||||
|
var className = cls.Last();
|
||||||
|
|
||||||
|
var rt = new StringBuilder();
|
||||||
|
|
||||||
|
rt.AppendLine("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
|
||||||
|
rt.AppendLine($"namespace { nameSpace} {{");
|
||||||
|
rt.AppendLine($"public class {className} : DistributedResource {{");
|
||||||
|
|
||||||
|
rt.AppendLine($"public {className}(DistributedConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) {{}}");
|
||||||
|
rt.AppendLine($"public {className}() {{}}");
|
||||||
|
|
||||||
|
foreach (var f in template.Functions)
|
||||||
|
{
|
||||||
|
var rtTypeName = GetTypeName(f.ReturnType, templates);
|
||||||
|
rt.Append($"public AsyncReply<{rtTypeName}> {f.Name}(");
|
||||||
|
rt.Append(string.Join(",", f.Arguments.Select(x => GetTypeName(x.Type, templates) + " " + x.Name)));
|
||||||
|
|
||||||
|
rt.AppendLine(") {");
|
||||||
|
rt.AppendLine($"var rt = new AsyncReply<{rtTypeName}>();");
|
||||||
|
rt.AppendLine($"_InvokeByArrayArguments({f.Index}, new object[] {{ { string.Join(", ", f.Arguments.Select(x => x.Name)) } }})");
|
||||||
|
rt.AppendLine($".Then(x => rt.Trigger(({rtTypeName})x))");
|
||||||
|
rt.AppendLine($".Error(x => rt.TriggerError(x))");
|
||||||
|
rt.AppendLine($".Chunk(x => rt.TriggerChunk(x));");
|
||||||
|
rt.AppendLine("return rt; }");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var p in template.Properties)
|
||||||
|
{
|
||||||
|
var ptTypeName = GetTypeName(p.ValueType, templates);
|
||||||
|
rt.AppendLine($"public {ptTypeName} {p.Name} {{");
|
||||||
|
rt.AppendLine($"get => ({ptTypeName})properties[{p.Index}];");
|
||||||
|
rt.AppendLine($"set => _Set({p.Index}, value);");
|
||||||
|
rt.AppendLine("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (template.Events.Length > 0)
|
||||||
|
{
|
||||||
|
rt.AppendLine("protected override void _EmitEventByIndex(byte index, object args) {");
|
||||||
|
rt.AppendLine("switch (index) {");
|
||||||
|
|
||||||
|
var eventsList = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (var e in template.Events)
|
||||||
|
{
|
||||||
|
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};");
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.AppendLine("}}");
|
||||||
|
|
||||||
|
rt.AppendLine(eventsList.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.AppendLine("\r\n}\r\n}");
|
||||||
|
|
||||||
|
return rt.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GenerateModel(GeneratorExecutionContext context, ResourceTemplate[] templates)
|
||||||
|
{
|
||||||
|
foreach (var tmp in templates)
|
||||||
|
{
|
||||||
|
var source = GenerateClass(tmp, templates);
|
||||||
|
//File.WriteAllText($@"C:\gen\{tmp.ClassName}.cs", source);
|
||||||
|
context.AddSource(tmp.ClassName + "_esiur.cs", source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate info class
|
||||||
|
|
||||||
|
var gen = "using System; \r\n namespace Esiur { public static class Generated { public static Type[] Types {get;} = new Type[]{ " +
|
||||||
|
string.Join(",", templates.Select(x => $"typeof({x.ClassName})"))
|
||||||
|
+ " }; \r\n } \r\n}";
|
||||||
|
|
||||||
|
//File.WriteAllText($@"C:\gen\Esiur.Generated.cs", gen);
|
||||||
|
|
||||||
|
context.AddSource("Esiur.Generated.cs", gen);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void Execute(GeneratorExecutionContext context)
|
public void Execute(GeneratorExecutionContext context)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!(context.SyntaxContextReceiver is ResourceGeneratorReceiver receiver))
|
if (!(context.SyntaxContextReceiver is ResourceGeneratorReceiver receiver))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try
|
//if (receiver.Imports.Count > 0 && !Debugger.IsAttached)
|
||||||
{
|
|
||||||
//#if DEBUG
|
|
||||||
// if (!Debugger.IsAttached)
|
|
||||||
//{
|
//{
|
||||||
// Debugger.Launch();
|
// Debugger.Launch();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
foreach (var path in receiver.Imports)
|
||||||
|
{
|
||||||
|
if (!urlRegex.IsMatch(path))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
//File.WriteAllLines("C:\\gen\\ref.log", context.Compilation.ReferencedAssemblyNames.Select(x => x.ToString()));
|
||||||
|
|
||||||
|
if (cache.Contains(path))
|
||||||
|
{
|
||||||
|
GenerateModel(context, cache[path]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Syncronization
|
||||||
|
//if (inProgress.Contains(path))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
//inProgress.Add(path);
|
||||||
|
|
||||||
|
var url = urlRegex.Split(path);
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var con = Warehouse.Get<DistributedConnection>(url[1] + "://" + url[2]).Wait(20000);
|
||||||
|
var templates = con.GetLinkTemplates(url[3]).Wait(60000);
|
||||||
|
|
||||||
|
cache[path] = templates;
|
||||||
|
|
||||||
|
// make sources
|
||||||
|
GenerateModel(context, templates);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ReportError(context, ex.Source, ex.Message, "Esiur");
|
||||||
|
System.IO.File.AppendAllText("c:\\gen\\error.log", ex.ToString() + "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//inProgress.Remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//#if DEBUG
|
||||||
|
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
//var toImplement = receiver.Classes.Where(x => x.Fields.Length > 0);
|
//var toImplement = receiver.Classes.Where(x => x.Fields.Length > 0);
|
||||||
|
|
||||||
foreach (var ci in receiver.Classes)
|
foreach (var ci in receiver.Classes.Values)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
var code = @$"using Esiur.Resource;
|
var code = @$"using Esiur.Resource;
|
||||||
using Esiur.Core;
|
using Esiur.Core;
|
||||||
namespace { ci.ClassSymbol.ContainingNamespace.ToDisplayString() } {{
|
namespace { ci.ClassSymbol.ContainingNamespace.ToDisplayString() } {{
|
||||||
";
|
";
|
||||||
|
|
||||||
if (ci.ImplementInterface)
|
if (ci.HasInterface)
|
||||||
code += $"public partial class {ci.Name} {{";
|
code += $"public partial class {ci.Name} {{";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -52,7 +256,7 @@ public event DestroyedEvent OnDestroy;
|
|||||||
public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
|
public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
|
||||||
";
|
";
|
||||||
|
|
||||||
if (!ci.ImplementTrigger)
|
if (!ci.HasTrigger)
|
||||||
code += "public AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);\r\n";
|
code += "public AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,11 +274,12 @@ public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
|
|||||||
|
|
||||||
//System.IO.File.WriteAllText("c:\\gen\\" + ci.Name + "_esiur.cs", code);
|
//System.IO.File.WriteAllText("c:\\gen\\" + ci.Name + "_esiur.cs", code);
|
||||||
context.AddSource(ci.Name + "_esiur.cs", code);
|
context.AddSource(ci.Name + "_esiur.cs", code);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
catch (Exception ex)
|
||||||
catch //(Exception ex)
|
|
||||||
{
|
{
|
||||||
//System.IO.File.AppendAllText("c:\\gen\\error.log", ex.ToString() + "\r\n");
|
System.IO.File.AppendAllText("c:\\gen\\error.log", ci.Name + " " + ex.ToString() + "\r\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,10 @@ namespace Esiur.Proxy
|
|||||||
public struct ResourceGeneratorClassInfo
|
public struct ResourceGeneratorClassInfo
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public bool ImplementInterface { get; set; }
|
public bool HasInterface { get; set; }
|
||||||
|
|
||||||
public bool ImplementTrigger { get; set; }
|
public bool HasTrigger { get; set; }
|
||||||
public IFieldSymbol[] Fields { get; set; }
|
public List<IFieldSymbol> Fields { get; set; }
|
||||||
public ITypeSymbol ClassSymbol { get; set; }
|
public ITypeSymbol ClassSymbol { get; set; }
|
||||||
|
|
||||||
public ClassDeclarationSyntax ClassDeclaration { get; set; }
|
public ClassDeclarationSyntax ClassDeclaration { get; set; }
|
||||||
|
@ -11,7 +11,9 @@ namespace Esiur.Proxy
|
|||||||
public class ResourceGeneratorReceiver : ISyntaxContextReceiver
|
public class ResourceGeneratorReceiver : ISyntaxContextReceiver
|
||||||
{
|
{
|
||||||
|
|
||||||
public List<ResourceGeneratorClassInfo> Classes { get; } = new();
|
public Dictionary<string, ResourceGeneratorClassInfo> Classes { get; } = new();
|
||||||
|
|
||||||
|
public List<string> Imports { get; } = new ();
|
||||||
|
|
||||||
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
|
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
|
||||||
{
|
{
|
||||||
@ -20,8 +22,21 @@ namespace Esiur.Proxy
|
|||||||
{
|
{
|
||||||
var cds = context.Node as ClassDeclarationSyntax;
|
var cds = context.Node as ClassDeclarationSyntax;
|
||||||
var cls = context.SemanticModel.GetDeclaredSymbol(cds) as ITypeSymbol;
|
var cls = context.SemanticModel.GetDeclaredSymbol(cds) as ITypeSymbol;
|
||||||
|
var attrs = cls.GetAttributes();
|
||||||
|
|
||||||
if (cls.GetAttributes().Any(a => a.AttributeClass.ToDisplayString() == "Esiur.Resource.ResourceAttribute"))
|
var imports = attrs.Where(a => a.AttributeClass.ToDisplayString() == "Esiur.Resource.ImportAttribute");
|
||||||
|
|
||||||
|
foreach (var import in imports)
|
||||||
|
{
|
||||||
|
// Debugger.Launch();
|
||||||
|
|
||||||
|
var url = import.ConstructorArguments.First().Value.ToString();
|
||||||
|
|
||||||
|
if (!Imports.Contains(url))
|
||||||
|
Imports.Add(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.Any(a => a.AttributeClass.ToDisplayString() == "Esiur.Resource.ResourceAttribute"))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@ -46,15 +61,32 @@ namespace Esiur.Proxy
|
|||||||
|
|
||||||
|
|
||||||
// get fields
|
// get fields
|
||||||
Classes.Add(new ResourceGeneratorClassInfo()
|
|
||||||
|
var fullName = cls.ContainingAssembly + "." + cls.Name;
|
||||||
|
|
||||||
|
// Partial class check
|
||||||
|
if (Classes.ContainsKey(fullName))
|
||||||
|
{
|
||||||
|
// append fields
|
||||||
|
var c = Classes[fullName];
|
||||||
|
c.Fields.AddRange(fields);
|
||||||
|
if (!c.HasInterface)
|
||||||
|
c.HasInterface = cls.Interfaces.Any(x => x.ToDisplayString() == "Esiur.Resource.IResource");
|
||||||
|
if (!c.HasTrigger)
|
||||||
|
c.HasTrigger = hasTrigger;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Classes.Add(fullName, new ResourceGeneratorClassInfo()
|
||||||
{
|
{
|
||||||
Name = cls.Name,
|
Name = cls.Name,
|
||||||
ClassDeclaration = cds,
|
ClassDeclaration = cds,
|
||||||
ClassSymbol = cls,
|
ClassSymbol = cls,
|
||||||
Fields = fields,
|
Fields = fields.ToList(),
|
||||||
ImplementInterface = cls.Interfaces.Any(x => x.ToDisplayString() == "Esiur.Resource.IResource"),
|
HasInterface = cls.Interfaces.Any(x => x.ToDisplayString() == "Esiur.Resource.IResource"),
|
||||||
ImplementTrigger = hasTrigger
|
HasTrigger = hasTrigger
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
15
Esiur/Resource/ImportAttribute.cs
Normal file
15
Esiur/Resource/ImportAttribute.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Resource
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class ImportAttribute:Attribute
|
||||||
|
{
|
||||||
|
public ImportAttribute(string url)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -185,8 +185,8 @@ namespace Esiur.Resource
|
|||||||
var at = template.GetAttributeTemplate(kv.Key);
|
var at = template.GetAttributeTemplate(kv.Key);
|
||||||
|
|
||||||
if (at != null)
|
if (at != null)
|
||||||
if (at.Info.CanWrite)
|
if (at.PropertyInfo.CanWrite)
|
||||||
at.Info.SetValue(res, DC.CastConvert(kv.Value, at.Info.PropertyType));
|
at.PropertyInfo.SetValue(res, DC.CastConvert(kv.Value, at.PropertyInfo.PropertyType));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,17 +354,17 @@ namespace Esiur.Resource
|
|||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pt.Info.PropertyType == typeof(DistributedPropertyContext))
|
if (pt.PropertyInfo.PropertyType == typeof(DistributedPropertyContext))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
if (pt.Info.CanWrite)
|
if (pt.PropertyInfo.CanWrite)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
loading = true;
|
loading = true;
|
||||||
|
|
||||||
pt.Info.SetValue(res, DC.CastConvert(value, pt.Info.PropertyType));
|
pt.PropertyInfo.SetValue(res, DC.CastConvert(value, pt.PropertyInfo.PropertyType));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -453,7 +453,7 @@ namespace Esiur.Resource
|
|||||||
|
|
||||||
if (resource.TryGetTarget(out res))
|
if (resource.TryGetTarget(out res))
|
||||||
{
|
{
|
||||||
var rt = pt.Info.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]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -628,7 +628,7 @@ namespace Esiur.Resource
|
|||||||
|
|
||||||
var pt = template.GetPropertyTemplateByName(name);
|
var pt = template.GetPropertyTemplateByName(name);
|
||||||
|
|
||||||
if (pt != null && pt.Info != null)
|
if (pt != null && pt.PropertyInfo != null)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
#if NETSTANDARD
|
#if NETSTANDARD
|
||||||
@ -649,7 +649,7 @@ namespace Esiur.Resource
|
|||||||
|
|
||||||
IResource res;
|
IResource res;
|
||||||
if (resource.TryGetTarget(out res))
|
if (resource.TryGetTarget(out res))
|
||||||
value = pt.Info.GetValue(res, null);
|
value = pt.PropertyInfo.GetValue(res, null);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = null;
|
value = null;
|
||||||
@ -900,28 +900,30 @@ namespace Esiur.Resource
|
|||||||
//if (evt.EventHandlerType != typeof(ResourceEventHanlder))
|
//if (evt.EventHandlerType != typeof(ResourceEventHanlder))
|
||||||
// continue;
|
// continue;
|
||||||
|
|
||||||
if (evt.Info == null)
|
if (evt.EventInfo == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (evt.Info.EventHandlerType == typeof(ResourceEventHanlder))
|
var eventGenericType = evt.EventInfo.EventHandlerType.GetGenericTypeDefinition();
|
||||||
|
|
||||||
|
if (eventGenericType == typeof(ResourceEventHanlder<>))
|
||||||
{
|
{
|
||||||
|
|
||||||
// var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
|
// var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
|
||||||
// if (ca.Length == 0)
|
// if (ca.Length == 0)
|
||||||
// continue;
|
// continue;
|
||||||
|
|
||||||
ResourceEventHanlder proxyDelegate = (args) => EmitResourceEvent(evt.Name, args);
|
ResourceEventHanlder<object> proxyDelegate = (args) => EmitResourceEvent(evt.Name, args);
|
||||||
evt.Info.AddEventHandler(resource, proxyDelegate);
|
evt.EventInfo.AddEventHandler(resource, proxyDelegate);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (evt.Info.EventHandlerType == typeof(CustomResourceEventHanlder))
|
else if (eventGenericType == typeof(CustomResourceEventHanlder<>))
|
||||||
{
|
{
|
||||||
//var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
|
//var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
|
||||||
//if (ca.Length == 0)
|
//if (ca.Length == 0)
|
||||||
// continue;
|
// continue;
|
||||||
|
|
||||||
CustomResourceEventHanlder proxyDelegate = (issuer, receivers, args) => EmitCustomResourceEvent(issuer, receivers, evt.Name, args);
|
CustomResourceEventHanlder<object> proxyDelegate = (issuer, receivers, args) => EmitCustomResourceEvent(issuer, receivers, evt.Name, args);
|
||||||
evt.Info.AddEventHandler(resource, proxyDelegate);
|
evt.EventInfo.AddEventHandler(resource, proxyDelegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,12 +33,14 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Esiur.Resource
|
namespace Esiur.Resource
|
||||||
{
|
{
|
||||||
public delegate void ResourceEventHanlder(object args);
|
public delegate R DCovariant<out R>();
|
||||||
|
|
||||||
|
public delegate void ResourceEventHanlder<in T>(T argument);
|
||||||
// public delegate void CustomUsersEventHanlder(string[] usernames, params object[] args);
|
// public delegate void CustomUsersEventHanlder(string[] usernames, params object[] args);
|
||||||
//public delegate void CustomReceiversEventHanlder(DistributedConnection[] connections, params object[] args);
|
//public delegate void CustomReceiversEventHanlder(DistributedConnection[] connections, params object[] args);
|
||||||
//public delegate void CustomInquirerEventHanlder(object inquirer, params object[] args);
|
//public delegate void CustomInquirerEventHanlder(object inquirer, params object[] args);
|
||||||
|
|
||||||
public delegate void CustomResourceEventHanlder(object issuer, Func<Session, bool> receivers, object args);// object issuer, Session[] receivers, params object[] args);
|
public delegate void CustomResourceEventHanlder<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);
|
// public delegate void CustomReceiversEventHanlder(string[] usernames, DistributedConnection[] connections, params object[] args);
|
||||||
|
|
||||||
|
49
Esiur/Resource/Template/ArgumentTemplate.cs
Normal file
49
Esiur/Resource/Template/ArgumentTemplate.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using Esiur.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Esiur.Resource.Template
|
||||||
|
{
|
||||||
|
public class ArgumentTemplate
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public TemplateDataType Type { get; set; }
|
||||||
|
|
||||||
|
public ParameterInfo ParameterInfo { get; set; }
|
||||||
|
|
||||||
|
public static (uint, ArgumentTemplate) Parse(byte[] data, uint offset)
|
||||||
|
{
|
||||||
|
var cs = (uint)data[offset++];
|
||||||
|
var name = DC.GetString(data, offset, cs);
|
||||||
|
offset += cs;
|
||||||
|
var (size, type) = TemplateDataType.Parse(data, offset);
|
||||||
|
|
||||||
|
return (cs + 1 + size, new ArgumentTemplate(name, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgumentTemplate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgumentTemplate(string name, TemplateDataType type)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Compose()
|
||||||
|
{
|
||||||
|
var name = DC.ToBytes(Name);
|
||||||
|
|
||||||
|
return new BinaryList()
|
||||||
|
.AddUInt8((byte)name.Length)
|
||||||
|
.AddUInt8Array(name)
|
||||||
|
.AddUInt8Array(Type.Compose())
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ namespace Esiur.Resource.Template
|
|||||||
{
|
{
|
||||||
public class AttributeTemplate : MemberTemplate
|
public class AttributeTemplate : MemberTemplate
|
||||||
{
|
{
|
||||||
public PropertyInfo Info
|
public PropertyInfo PropertyInfo
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
@ -18,7 +18,9 @@ namespace Esiur.Resource.Template
|
|||||||
|
|
||||||
public bool Listenable { get; set; }
|
public bool Listenable { get; set; }
|
||||||
|
|
||||||
public EventInfo Info { get; set; }
|
public EventInfo EventInfo { get; set; }
|
||||||
|
|
||||||
|
public TemplateDataType ArgumentType { get; set; }
|
||||||
|
|
||||||
public override byte[] Compose()
|
public override byte[] Compose()
|
||||||
{
|
{
|
||||||
@ -26,12 +28,12 @@ namespace Esiur.Resource.Template
|
|||||||
|
|
||||||
if (Expansion != null)
|
if (Expansion != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
var exp = DC.ToBytes(Expansion);
|
var exp = DC.ToBytes(Expansion);
|
||||||
return new BinaryList()
|
return new BinaryList()
|
||||||
.AddUInt8(Listenable ? (byte) 0x58 : (byte) 0x50)
|
.AddUInt8(Listenable ? (byte) 0x58 : (byte) 0x50)
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
.AddUInt8Array(name)
|
.AddUInt8Array(name)
|
||||||
|
.AddUInt8Array(ArgumentType.Compose())
|
||||||
.AddInt32(exp.Length)
|
.AddInt32(exp.Length)
|
||||||
.AddUInt8Array(exp)
|
.AddUInt8Array(exp)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@ -41,15 +43,17 @@ namespace Esiur.Resource.Template
|
|||||||
.AddUInt8(Listenable ? (byte) 0x48 : (byte) 0x40)
|
.AddUInt8(Listenable ? (byte) 0x48 : (byte) 0x40)
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
.AddUInt8Array(name)
|
.AddUInt8Array(name)
|
||||||
|
.AddUInt8Array(ArgumentType.Compose())
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public EventTemplate(ResourceTemplate template, byte index, string name, string expansion = null, bool listenable=false)
|
public EventTemplate(ResourceTemplate template, byte index, string name, TemplateDataType argumentType, string expansion = null, bool listenable=false)
|
||||||
:base(template, MemberType.Property, index, name)
|
:base(template, MemberType.Property, index, name)
|
||||||
{
|
{
|
||||||
this.Expansion = expansion;
|
this.Expansion = expansion;
|
||||||
this.Listenable = listenable;
|
this.Listenable = listenable;
|
||||||
|
this.ArgumentType = argumentType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -16,7 +17,17 @@ namespace Esiur.Resource.Template
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsVoid
|
//public bool IsVoid
|
||||||
|
//{
|
||||||
|
// get;
|
||||||
|
// set;
|
||||||
|
//}
|
||||||
|
|
||||||
|
public TemplateDataType ReturnType { get; set; }
|
||||||
|
|
||||||
|
public ArgumentTemplate[] Arguments { get; set; }
|
||||||
|
|
||||||
|
public MethodInfo MethodInfo
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
@ -25,30 +36,40 @@ namespace Esiur.Resource.Template
|
|||||||
|
|
||||||
public override byte[] Compose()
|
public override byte[] Compose()
|
||||||
{
|
{
|
||||||
|
|
||||||
var name = base.Compose();
|
var name = base.Compose();
|
||||||
|
|
||||||
|
var bl = new BinaryList()
|
||||||
|
//.AddUInt8(Expansion != null ? (byte)0x10 : (byte)0)
|
||||||
|
.AddUInt8((byte)name.Length)
|
||||||
|
.AddUInt8Array(name)
|
||||||
|
.AddUInt8Array(ReturnType.Compose())
|
||||||
|
.AddUInt8((byte)Arguments.Length);
|
||||||
|
|
||||||
|
for (var i = 0; i < Arguments.Length; i++)
|
||||||
|
bl.AddUInt8Array(Arguments[i].Compose());
|
||||||
|
|
||||||
|
|
||||||
if (Expansion != null)
|
if (Expansion != null)
|
||||||
{
|
{
|
||||||
var exp = DC.ToBytes(Expansion);
|
var exp = DC.ToBytes(Expansion);
|
||||||
return new BinaryList().AddUInt8((byte)(0x10 | (IsVoid ? 0x8 : 0x0)))
|
bl.AddInt32(exp.Length)
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8Array(exp);
|
||||||
.AddUInt8Array(name)
|
bl.InsertUInt8(0, 0x10);
|
||||||
.AddInt32(exp.Length)
|
|
||||||
.AddUInt8Array(exp)
|
|
||||||
.ToArray();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return new BinaryList().AddUInt8((byte)(IsVoid ? 0x8 : 0x0))
|
bl.InsertUInt8(0, 0x0);
|
||||||
.AddUInt8((byte)name.Length)
|
|
||||||
.AddUInt8Array(name)
|
return bl.ToArray();
|
||||||
.ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public FunctionTemplate(ResourceTemplate template, byte index, string name,bool isVoid, string expansion = null)
|
public FunctionTemplate(ResourceTemplate template, byte index, string name, ArgumentTemplate[] arguments, TemplateDataType returnType, string expansion = null)
|
||||||
: base(template, MemberType.Property, index, name)
|
: base(template, MemberType.Property, index, name)
|
||||||
{
|
{
|
||||||
this.IsVoid = isVoid;
|
//this.IsVoid = isVoid;
|
||||||
|
this.Arguments = arguments;
|
||||||
|
this.ReturnType = returnType;
|
||||||
this.Expansion = expansion;
|
this.Expansion = expansion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,15 @@ namespace Esiur.Resource.Template
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public PropertyInfo Info
|
public PropertyInfo PropertyInfo
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TemplateDataType ValueType { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public bool Serilize
|
public bool Serilize
|
||||||
{
|
{
|
||||||
@ -32,7 +35,8 @@ namespace Esiur.Resource.Template
|
|||||||
*/
|
*/
|
||||||
//bool ReadOnly;
|
//bool ReadOnly;
|
||||||
//IIPTypes::DataType ReturnType;
|
//IIPTypes::DataType ReturnType;
|
||||||
public PropertyPermission Permission {
|
public PropertyPermission Permission
|
||||||
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
@ -84,6 +88,7 @@ namespace Esiur.Resource.Template
|
|||||||
.AddUInt8((byte)(0x38 | pv))
|
.AddUInt8((byte)(0x38 | pv))
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
.AddUInt8Array(name)
|
.AddUInt8Array(name)
|
||||||
|
.AddUInt8Array(ValueType.Compose())
|
||||||
.AddInt32(wexp.Length)
|
.AddInt32(wexp.Length)
|
||||||
.AddUInt8Array(wexp)
|
.AddUInt8Array(wexp)
|
||||||
.AddInt32(rexp.Length)
|
.AddInt32(rexp.Length)
|
||||||
@ -97,6 +102,7 @@ namespace Esiur.Resource.Template
|
|||||||
.AddUInt8((byte)(0x30 | pv))
|
.AddUInt8((byte)(0x30 | pv))
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
.AddUInt8Array(name)
|
.AddUInt8Array(name)
|
||||||
|
.AddUInt8Array(ValueType.Compose())
|
||||||
.AddInt32(wexp.Length)
|
.AddInt32(wexp.Length)
|
||||||
.AddUInt8Array(wexp)
|
.AddUInt8Array(wexp)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@ -108,25 +114,30 @@ namespace Esiur.Resource.Template
|
|||||||
.AddUInt8((byte)(0x28 | pv))
|
.AddUInt8((byte)(0x28 | pv))
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
.AddUInt8Array(name)
|
.AddUInt8Array(name)
|
||||||
|
.AddUInt8Array(ValueType.Compose())
|
||||||
.AddInt32(rexp.Length)
|
.AddInt32(rexp.Length)
|
||||||
.AddUInt8Array(rexp)
|
.AddUInt8Array(rexp)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return new BinaryList()
|
return new BinaryList()
|
||||||
.AddUInt8((byte)(0x20 | pv))
|
.AddUInt8((byte)(0x20 | pv))
|
||||||
.AddUInt8((byte)name.Length)
|
.AddUInt8((byte)name.Length)
|
||||||
.AddUInt8Array(name)
|
.AddUInt8Array(name)
|
||||||
|
.AddUInt8Array(ValueType.Compose())
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PropertyTemplate(ResourceTemplate template, byte index, string name, string read = null, string write = null, bool recordable = false)
|
public PropertyTemplate(ResourceTemplate template, byte index, string name, TemplateDataType valueType, string read = null, string write = null, bool recordable = false)
|
||||||
: base(template, MemberType.Property, index, name)
|
: base(template, MemberType.Property, index, name)
|
||||||
{
|
{
|
||||||
this.Recordable = recordable;
|
this.Recordable = recordable;
|
||||||
//this.Storage = storage;
|
//this.Storage = storage;
|
||||||
this.ReadExpansion = read;
|
this.ReadExpansion = read;
|
||||||
this.WriteExpansion = write;
|
this.WriteExpansion = write;
|
||||||
|
this.ValueType = valueType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ namespace Esiur.Resource.Template
|
|||||||
{
|
{
|
||||||
public class ResourceTemplate
|
public class ResourceTemplate
|
||||||
{
|
{
|
||||||
|
|
||||||
Guid classId;
|
Guid classId;
|
||||||
string className;
|
string className;
|
||||||
List<MemberTemplate> members = new List<MemberTemplate>();
|
List<MemberTemplate> members = new List<MemberTemplate>();
|
||||||
@ -31,6 +32,8 @@ namespace Esiur.Resource.Template
|
|||||||
get { return content; }
|
get { return content; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type RuntimeType { get; set; }
|
||||||
|
|
||||||
public MemberTemplate GetMemberTemplate(MemberInfo member)
|
public MemberTemplate GetMemberTemplate(MemberInfo member)
|
||||||
{
|
{
|
||||||
if (member is MethodInfo)
|
if (member is MethodInfo)
|
||||||
@ -135,19 +138,136 @@ namespace Esiur.Resource.Template
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Guid GetTypeGuid(Type type) => GetTypeGuid(type.FullName);
|
||||||
|
|
||||||
|
public static Guid GetTypeGuid(string typeName)
|
||||||
|
{
|
||||||
|
var tn = Encoding.UTF8.GetBytes(typeName);
|
||||||
|
var hash = SHA256.Create().ComputeHash(tn).Clip(0, 16);
|
||||||
|
|
||||||
|
return new Guid(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Type GetElementType(Type type) => type switch
|
||||||
|
{
|
||||||
|
{ IsArray: true } => type.GetElementType(),
|
||||||
|
{ IsEnum: true } => type.GetEnumUnderlyingType(),
|
||||||
|
(_) => type
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static ResourceTemplate[] GetRuntimeTypes(ResourceTemplate template)
|
||||||
|
{
|
||||||
|
|
||||||
|
var list = new List<ResourceTemplate>();
|
||||||
|
|
||||||
|
list.Add(template);
|
||||||
|
|
||||||
|
Action<ResourceTemplate, List<ResourceTemplate>> getRuntimeTypes = null;
|
||||||
|
|
||||||
|
getRuntimeTypes = (ResourceTemplate tmp, List<ResourceTemplate> bag) =>
|
||||||
|
{
|
||||||
|
if (template.RuntimeType == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// functions
|
||||||
|
foreach (var f in tmp.functions)
|
||||||
|
{
|
||||||
|
var frtt = Warehouse.GetTemplate(GetElementType(f.MethodInfo.ReturnType));
|
||||||
|
if (frtt != null)
|
||||||
|
{
|
||||||
|
if (!bag.Contains(frtt))
|
||||||
|
{
|
||||||
|
list.Add(frtt);
|
||||||
|
getRuntimeTypes(frtt, bag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = f.MethodInfo.GetParameters();
|
||||||
|
|
||||||
|
for(var i = 0; i < args.Length - 1; i++)
|
||||||
|
{
|
||||||
|
var fpt = Warehouse.GetTemplate(GetElementType(args[i].ParameterType));
|
||||||
|
if (fpt != null)
|
||||||
|
{
|
||||||
|
if (!bag.Contains(fpt))
|
||||||
|
{
|
||||||
|
bag.Add(fpt);
|
||||||
|
getRuntimeTypes(fpt, bag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip DistributedConnection argument
|
||||||
|
if (args.Length > 0)
|
||||||
|
{
|
||||||
|
var last = args.Last();
|
||||||
|
if (last.ParameterType != typeof(DistributedConnection))
|
||||||
|
{
|
||||||
|
var fpt = Warehouse.GetTemplate(GetElementType(last.ParameterType));
|
||||||
|
if (fpt != null)
|
||||||
|
{
|
||||||
|
if (!bag.Contains(fpt))
|
||||||
|
{
|
||||||
|
bag.Add(fpt);
|
||||||
|
getRuntimeTypes(fpt, bag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// properties
|
||||||
|
foreach (var p in tmp.properties)
|
||||||
|
{
|
||||||
|
var pt = Warehouse.GetTemplate(GetElementType(p.PropertyInfo.PropertyType));
|
||||||
|
if (pt != null)
|
||||||
|
{
|
||||||
|
if (!bag.Contains(pt))
|
||||||
|
{
|
||||||
|
bag.Add(pt);
|
||||||
|
getRuntimeTypes(pt, bag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// events
|
||||||
|
foreach (var e in tmp.events)
|
||||||
|
{
|
||||||
|
var et = Warehouse.GetTemplate(GetElementType(e.EventInfo.EventHandlerType.GenericTypeArguments[0]));
|
||||||
|
|
||||||
|
if (et != null)
|
||||||
|
{
|
||||||
|
if (!bag.Contains(et))
|
||||||
|
{
|
||||||
|
bag.Add(et);
|
||||||
|
getRuntimeTypes(et, bag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getRuntimeTypes(template, list);
|
||||||
|
return list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public ResourceTemplate(Type type)
|
public ResourceTemplate(Type type)
|
||||||
{
|
{
|
||||||
|
if (!Codec.ImplementsInterface(type, typeof(IResource)))
|
||||||
|
throw new Exception("Type is not a resource.");
|
||||||
|
|
||||||
type = ResourceProxy.GetBaseType(type);
|
type = ResourceProxy.GetBaseType(type);
|
||||||
|
|
||||||
// set guid
|
RuntimeType = type;
|
||||||
|
|
||||||
var typeName = Encoding.UTF8.GetBytes(type.FullName);
|
|
||||||
var hash = SHA256.Create().ComputeHash(typeName).Clip(0, 16);
|
|
||||||
|
|
||||||
classId = new Guid(hash);
|
|
||||||
className = type.FullName;
|
className = type.FullName;
|
||||||
|
|
||||||
|
//Console.WriteLine($"Creating {className}");
|
||||||
|
|
||||||
|
// set guid
|
||||||
|
classId = GetTypeGuid(className);
|
||||||
|
|
||||||
#if NETSTANDARD
|
#if NETSTANDARD
|
||||||
PropertyInfo[] propsInfo = type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
|
PropertyInfo[] propsInfo = type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
|
||||||
@ -176,7 +296,8 @@ namespace Esiur.Resource.Template
|
|||||||
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
|
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
|
||||||
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
|
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
|
||||||
|
|
||||||
var pt = new PropertyTemplate(this, i++, pi.Name);
|
var pt = new PropertyTemplate(this, i++, pi.Name, TemplateDataType.FromType(pi.PropertyType));
|
||||||
|
|
||||||
if (storageAttr != null)
|
if (storageAttr != null)
|
||||||
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
||||||
|
|
||||||
@ -185,7 +306,7 @@ namespace Esiur.Resource.Template
|
|||||||
else
|
else
|
||||||
pt.ReadExpansion = pi.PropertyType.Name;
|
pt.ReadExpansion = pi.PropertyType.Name;
|
||||||
|
|
||||||
pt.Info = pi;
|
pt.PropertyInfo = pi;
|
||||||
//pt.Serilize = publicAttr.Serialize;
|
//pt.Serilize = publicAttr.Serialize;
|
||||||
properties.Add(pt);
|
properties.Add(pt);
|
||||||
}
|
}
|
||||||
@ -195,7 +316,7 @@ namespace Esiur.Resource.Template
|
|||||||
if (attributeAttr != null)
|
if (attributeAttr != null)
|
||||||
{
|
{
|
||||||
var at = new AttributeTemplate(this, 0, pi.Name);
|
var at = new AttributeTemplate(this, 0, pi.Name);
|
||||||
at.Info = pi;
|
at.PropertyInfo = pi;
|
||||||
attributes.Add(at);
|
attributes.Add(at);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,8 +332,9 @@ namespace Esiur.Resource.Template
|
|||||||
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
|
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
|
||||||
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
|
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
|
||||||
|
|
||||||
var et = new EventTemplate(this, i++, ei.Name);
|
var argType = ei.EventHandlerType.GenericTypeArguments[0];
|
||||||
et.Info = ei;
|
var et = new EventTemplate(this, i++, ei.Name, TemplateDataType.FromType(argType));
|
||||||
|
et.EventInfo = ei;
|
||||||
|
|
||||||
if (annotationAttr != null)
|
if (annotationAttr != null)
|
||||||
et.Expansion = annotationAttr.Annotation;
|
et.Expansion = annotationAttr.Annotation;
|
||||||
@ -232,12 +354,32 @@ namespace Esiur.Resource.Template
|
|||||||
{
|
{
|
||||||
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
|
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
|
||||||
|
|
||||||
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void));
|
var returnType = TemplateDataType.FromType(mi.ReturnType);
|
||||||
|
|
||||||
|
var args = mi.GetParameters();
|
||||||
|
|
||||||
|
if (args.Length > 0)
|
||||||
|
{
|
||||||
|
if (args.Last().ParameterType == typeof(DistributedConnection))
|
||||||
|
args = args.Take(args.Count() - 1).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
var arguments = args.Select(x => new ArgumentTemplate()
|
||||||
|
{
|
||||||
|
Name = x.Name,
|
||||||
|
Type = TemplateDataType.FromType(x.ParameterType),
|
||||||
|
ParameterInfo = x
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var ft = new FunctionTemplate(this, i++, mi.Name, arguments, returnType);// mi.ReturnType == typeof(void));
|
||||||
|
|
||||||
if (annotationAttr != null)
|
if (annotationAttr != null)
|
||||||
ft.Expansion = annotationAttr.Annotation;
|
ft.Expansion = annotationAttr.Annotation;
|
||||||
else
|
else
|
||||||
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
|
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
|
||||||
|
|
||||||
|
ft.MethodInfo = mi;
|
||||||
functions.Add(ft);
|
functions.Add(ft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,8 +395,9 @@ namespace Esiur.Resource.Template
|
|||||||
{
|
{
|
||||||
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
|
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
|
||||||
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
|
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
|
||||||
|
var valueType = TemplateDataType.FromType(pi.PropertyType);
|
||||||
|
|
||||||
var pt = new PropertyTemplate(this, i++, pi.Name);//, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
|
var pt = new PropertyTemplate(this, i++, pi.Name, valueType);//, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
|
||||||
if (storageAttr != null)
|
if (storageAttr != null)
|
||||||
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
||||||
|
|
||||||
@ -263,7 +406,7 @@ namespace Esiur.Resource.Template
|
|||||||
else
|
else
|
||||||
pt.ReadExpansion = pi.PropertyType.Name;
|
pt.ReadExpansion = pi.PropertyType.Name;
|
||||||
|
|
||||||
pt.Info = pi;
|
pt.PropertyInfo = pi;
|
||||||
//pt.Serilize = publicAttr.Serialize;
|
//pt.Serilize = publicAttr.Serialize;
|
||||||
properties.Add(pt);
|
properties.Add(pt);
|
||||||
}
|
}
|
||||||
@ -273,7 +416,7 @@ namespace Esiur.Resource.Template
|
|||||||
if (attributeAttr != null)
|
if (attributeAttr != null)
|
||||||
{
|
{
|
||||||
var at = new AttributeTemplate(this, 0, pi.Name);
|
var at = new AttributeTemplate(this, 0, pi.Name);
|
||||||
at.Info = pi;
|
at.PropertyInfo = pi;
|
||||||
attributes.Add(at);
|
attributes.Add(at);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,8 +432,10 @@ namespace Esiur.Resource.Template
|
|||||||
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
|
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
|
||||||
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
|
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
|
||||||
|
|
||||||
var et = new EventTemplate(this, i++, ei.Name);
|
var argType = ei.EventHandlerType.GenericTypeArguments[0];
|
||||||
et.Info = ei;
|
|
||||||
|
var et = new EventTemplate(this, i++, ei.Name, TemplateDataType.FromType(argType));
|
||||||
|
et.EventInfo = ei;
|
||||||
|
|
||||||
if (annotationAttr != null)
|
if (annotationAttr != null)
|
||||||
et.Expansion = annotationAttr.Annotation;
|
et.Expansion = annotationAttr.Annotation;
|
||||||
@ -309,13 +454,32 @@ namespace Esiur.Resource.Template
|
|||||||
if (publicAttr != null)
|
if (publicAttr != null)
|
||||||
{
|
{
|
||||||
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
|
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
|
||||||
|
var returnType = TemplateDataType.FromType(mi.ReturnType);
|
||||||
|
|
||||||
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void));
|
var args = mi.GetParameters();
|
||||||
|
|
||||||
|
if (args.Length > 0)
|
||||||
|
{
|
||||||
|
if (args.Last().ParameterType == typeof(DistributedConnection))
|
||||||
|
args = args.Take(args.Count() - 1).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
var arguments = args.Select(x => new ArgumentTemplate()
|
||||||
|
{
|
||||||
|
Name = x.Name,
|
||||||
|
Type = TemplateDataType.FromType(x.ParameterType),
|
||||||
|
ParameterInfo = x
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var ft = new FunctionTemplate(this, i++, mi.Name, arguments, returnType);// mi.ReturnType == typeof(void));
|
||||||
|
|
||||||
if (annotationAttr != null)
|
if (annotationAttr != null)
|
||||||
ft.Expansion = annotationAttr.Annotation;
|
ft.Expansion = annotationAttr.Annotation;
|
||||||
else
|
else
|
||||||
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x=>x.ParameterType != typeof(DistributedConnection)).Select(x=> "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
|
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x=>x.ParameterType != typeof(DistributedConnection)).Select(x=> "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
|
||||||
|
|
||||||
|
ft.MethodInfo = mi;
|
||||||
functions.Add(ft);
|
functions.Add(ft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,11 +555,27 @@ namespace Esiur.Resource.Template
|
|||||||
if (type == 0) // function
|
if (type == 0) // function
|
||||||
{
|
{
|
||||||
string expansion = null;
|
string expansion = null;
|
||||||
var hasExpansion = ((data[offset] & 0x10) == 0x10);
|
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
|
||||||
var isVoid = ((data[offset++] & 0x08) == 0x08);
|
|
||||||
var name = data.GetString(offset + 1, data[offset]);
|
var name = data.GetString(offset + 1, data[offset]);
|
||||||
offset += (uint)data[offset] + 1;
|
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 ?
|
if (hasExpansion) // expansion ?
|
||||||
{
|
{
|
||||||
var cs = data.GetUInt32(offset);
|
var cs = data.GetUInt32(offset);
|
||||||
@ -404,7 +584,7 @@ namespace Esiur.Resource.Template
|
|||||||
offset += cs;
|
offset += cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ft = new FunctionTemplate(od, functionIndex++, name, isVoid, expansion);
|
var ft = new FunctionTemplate(od, functionIndex++, name, arguments.ToArray(), returnType, expansion);
|
||||||
|
|
||||||
od.functions.Add(ft);
|
od.functions.Add(ft);
|
||||||
}
|
}
|
||||||
@ -421,6 +601,10 @@ namespace Esiur.Resource.Template
|
|||||||
|
|
||||||
offset += (uint)data[offset] + 1;
|
offset += (uint)data[offset] + 1;
|
||||||
|
|
||||||
|
var (dts, valueType) = TemplateDataType.Parse(data, offset);
|
||||||
|
|
||||||
|
offset += dts;
|
||||||
|
|
||||||
if (hasReadExpansion) // expansion ?
|
if (hasReadExpansion) // expansion ?
|
||||||
{
|
{
|
||||||
var cs = data.GetUInt32(offset);
|
var cs = data.GetUInt32(offset);
|
||||||
@ -437,7 +621,7 @@ namespace Esiur.Resource.Template
|
|||||||
offset += cs;
|
offset += cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pt = new PropertyTemplate(od, propertyIndex++, name, readExpansion, writeExpansion, recordable);
|
var pt = new PropertyTemplate(od, propertyIndex++, name, valueType, readExpansion, writeExpansion, recordable);
|
||||||
|
|
||||||
od.properties.Add(pt);
|
od.properties.Add(pt);
|
||||||
}
|
}
|
||||||
@ -451,6 +635,10 @@ namespace Esiur.Resource.Template
|
|||||||
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
|
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
|
||||||
offset += (uint)data[offset] + 1;
|
offset += (uint)data[offset] + 1;
|
||||||
|
|
||||||
|
var (dts, argType) = TemplateDataType.Parse(data, offset);
|
||||||
|
|
||||||
|
offset += dts;
|
||||||
|
|
||||||
if (hasExpansion) // expansion ?
|
if (hasExpansion) // expansion ?
|
||||||
{
|
{
|
||||||
var cs = data.GetUInt32(offset);
|
var cs = data.GetUInt32(offset);
|
||||||
@ -459,7 +647,7 @@ namespace Esiur.Resource.Template
|
|||||||
offset += cs;
|
offset += cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
var et = new EventTemplate(od, eventIndex++, name, expansion, listenable);
|
var et = new EventTemplate(od, eventIndex++, name, argType, expansion, listenable);
|
||||||
|
|
||||||
od.events.Add(et);
|
od.events.Add(et);
|
||||||
|
|
||||||
|
118
Esiur/Resource/Template/TemplateDataType.cs
Normal file
118
Esiur/Resource/Template/TemplateDataType.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using Esiur.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Resource.Template
|
||||||
|
{
|
||||||
|
public struct TemplateDataType
|
||||||
|
{
|
||||||
|
public DataType Type { get; set; }
|
||||||
|
//public string TypeName { get; set; }
|
||||||
|
public ResourceTemplate TypeTemplate => TypeGuid == null ? null : Warehouse.GetTemplate((Guid)TypeGuid);
|
||||||
|
|
||||||
|
public Guid? TypeGuid { get; set; }
|
||||||
|
//public TemplateDataType(DataType type, string typeName)
|
||||||
|
//{
|
||||||
|
// Type = type;
|
||||||
|
// TypeName = typeName;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static TemplateDataType FromType(Type type)
|
||||||
|
{
|
||||||
|
|
||||||
|
var t = type switch
|
||||||
|
{
|
||||||
|
{ IsArray: true } => type.GetElementType(),
|
||||||
|
{ IsEnum: true } => type.GetEnumUnderlyingType(),
|
||||||
|
(_) => type
|
||||||
|
};
|
||||||
|
|
||||||
|
DataType dt = t switch
|
||||||
|
{
|
||||||
|
_ when t == typeof(bool) => DataType.Bool,
|
||||||
|
_ when t == typeof(char) => DataType.Char,
|
||||||
|
_ when t == typeof(byte) => DataType.UInt8,
|
||||||
|
_ when t == typeof(sbyte) => DataType.Int8,
|
||||||
|
_ when t == typeof(short) => DataType.Int16,
|
||||||
|
_ when t == typeof(ushort) => DataType.UInt16,
|
||||||
|
_ when t == typeof(int) => DataType.Int32,
|
||||||
|
_ when t == typeof(uint) => DataType.UInt32,
|
||||||
|
_ when t == typeof(long) => DataType.Int64,
|
||||||
|
_ when t == typeof(ulong) => DataType.UInt64,
|
||||||
|
_ when t == typeof(float) => DataType.Float32,
|
||||||
|
_ when t == typeof(double) => DataType.Float64,
|
||||||
|
_ when t == typeof(decimal) => DataType.Decimal,
|
||||||
|
_ when t == typeof(string) => DataType.String,
|
||||||
|
_ when t == typeof(DateTime) => DataType.DateTime,
|
||||||
|
_ when t == typeof(IResource) => DataType.Void, // Dynamic resource (unspecified type)
|
||||||
|
_ when typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => DataType.Structure,
|
||||||
|
_ when Codec.ImplementsInterface(t, typeof(IResource)) => DataType.Resource,
|
||||||
|
_ => DataType.Void
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//string tn = dt switch
|
||||||
|
//{
|
||||||
|
// DataType.Resource => t.FullName,
|
||||||
|
// DataType.Structure when t != typeof(Structure) => t.FullName,
|
||||||
|
// _ => null
|
||||||
|
//};
|
||||||
|
|
||||||
|
Guid? typeGuid = null;
|
||||||
|
|
||||||
|
if (dt == DataType.Resource)
|
||||||
|
typeGuid = ResourceTemplate.GetTypeGuid(t);
|
||||||
|
|
||||||
|
if (type.IsArray)
|
||||||
|
dt = (DataType)((byte)dt | 0x80);
|
||||||
|
|
||||||
|
return new TemplateDataType()
|
||||||
|
{
|
||||||
|
Type = dt,
|
||||||
|
TypeGuid = typeGuid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Compose()
|
||||||
|
{
|
||||||
|
if (Type == DataType.Resource ||
|
||||||
|
Type == DataType.ResourceArray)//||
|
||||||
|
//Type == DataType.DistributedResource ||
|
||||||
|
//Type == DataType.DistributedResourceArray ||
|
||||||
|
//Type == DataType.Structure ||
|
||||||
|
//Type == DataType.StructureArray)
|
||||||
|
{
|
||||||
|
var guid = DC.ToBytes((Guid)TypeGuid);
|
||||||
|
return new BinaryList()
|
||||||
|
.AddUInt8((byte)Type)
|
||||||
|
.AddUInt8Array(guid).ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new byte[] { (byte)Type };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => Type.ToString() + TypeTemplate != null ? "<" + TypeTemplate.ClassName + ">" : "";
|
||||||
|
|
||||||
|
|
||||||
|
public static (uint, TemplateDataType) Parse(byte[] data, uint offset)
|
||||||
|
{
|
||||||
|
var type = (DataType)data[offset++];
|
||||||
|
if (type == DataType.Resource ||
|
||||||
|
type == DataType.ResourceArray)//||
|
||||||
|
// type == DataType.DistributedResource ||
|
||||||
|
// type == DataType.DistributedResourceArray)// ||
|
||||||
|
// type == DataType.Structure ||
|
||||||
|
// type == DataType.StructureArray)
|
||||||
|
{
|
||||||
|
var guid = DC.GetGuid(data, offset);
|
||||||
|
return (17, new TemplateDataType() { Type = type, TypeGuid = guid });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (1, new TemplateDataType() { Type = type });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -113,6 +113,22 @@ namespace Esiur.Resource
|
|||||||
return new AsyncReply<IResource>(null);
|
return new AsyncReply<IResource>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void LoadGenerated()
|
||||||
|
{
|
||||||
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
var generatedType = assembly.GetType("Esiur.Generated");
|
||||||
|
if (generatedType != null)
|
||||||
|
{
|
||||||
|
var types = (Type[])generatedType.GetProperty("Types").GetValue(null);
|
||||||
|
foreach (var t in types)
|
||||||
|
{
|
||||||
|
PutTemplate(new ResourceTemplate(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open the warehouse.
|
/// Open the warehouse.
|
||||||
/// This function issues the initialize trigger to all stores and resources.
|
/// This function issues the initialize trigger to all stores and resources.
|
||||||
@ -123,6 +139,10 @@ namespace Esiur.Resource
|
|||||||
if (warehouseIsOpen)
|
if (warehouseIsOpen)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Load generated models
|
||||||
|
LoadGenerated();
|
||||||
|
|
||||||
|
|
||||||
warehouseIsOpen = true;
|
warehouseIsOpen = true;
|
||||||
|
|
||||||
var resSnap = resources.Select(x =>
|
var resSnap = resources.Select(x =>
|
||||||
@ -380,7 +400,8 @@ namespace Esiur.Resource
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path"></param>
|
/// <param name="path"></param>
|
||||||
/// <returns>Resource instance.</returns>
|
/// <returns>Resource instance.</returns>
|
||||||
public static async AsyncReply<IResource> Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null)
|
public static async AsyncReply<T> Get<T>(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null)
|
||||||
|
where T: IResource
|
||||||
{
|
{
|
||||||
//var rt = new AsyncReply<IResource>();
|
//var rt = new AsyncReply<IResource>();
|
||||||
|
|
||||||
@ -404,9 +425,9 @@ namespace Esiur.Resource
|
|||||||
//await Put(store, url[2], null, parent, null, 0, manager, attributes);
|
//await Put(store, url[2], null, parent, null, 0, manager, attributes);
|
||||||
|
|
||||||
if (url[3].Length > 0 && url[3] != "")
|
if (url[3].Length > 0 && url[3] != "")
|
||||||
return await store.Get(url[3]);
|
return (T)await store.Get(url[3]);
|
||||||
else
|
else
|
||||||
return store;
|
return (T)store;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -471,9 +492,9 @@ namespace Esiur.Resource
|
|||||||
var res = await Query(path);
|
var res = await Query(path);
|
||||||
|
|
||||||
if (res.Length == 0)
|
if (res.Length == 0)
|
||||||
return null;
|
return default(T);
|
||||||
else
|
else
|
||||||
return res.First();
|
return (T)res.First();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +524,7 @@ namespace Esiur.Resource
|
|||||||
if (parent != null)
|
if (parent != null)
|
||||||
throw new Exception("Parent can't be set when using path in instance name");
|
throw new Exception("Parent can't be set when using path in instance name");
|
||||||
|
|
||||||
parent = await Warehouse.Get(string.Join("/", path.Take(path.Length - 1)));
|
parent = await Warehouse.Get<IResource>(string.Join("/", path.Take(path.Length - 1)));
|
||||||
|
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
throw new Exception("Can't find parent");
|
throw new Exception("Can't find parent");
|
||||||
@ -517,6 +538,9 @@ namespace Esiur.Resource
|
|||||||
var resourceReference = new WeakReference<IResource>(resource);
|
var resourceReference = new WeakReference<IResource>(resource);
|
||||||
|
|
||||||
if (store == null)
|
if (store == null)
|
||||||
|
{
|
||||||
|
// assign parent's store as a store
|
||||||
|
if (parent != null)
|
||||||
{
|
{
|
||||||
// assign parent as a store
|
// assign parent as a store
|
||||||
if (parent is IStore)
|
if (parent is IStore)
|
||||||
@ -528,8 +552,7 @@ namespace Esiur.Resource
|
|||||||
list.Add(resourceReference);
|
list.Add(resourceReference);
|
||||||
//stores[store].Add(resourceReference);
|
//stores[store].Add(resourceReference);
|
||||||
}
|
}
|
||||||
// assign parent's store as a store
|
else
|
||||||
else if (parent != null)
|
|
||||||
{
|
{
|
||||||
store = parent.Instance.Store;
|
store = parent.Instance.Store;
|
||||||
|
|
||||||
@ -537,8 +560,7 @@ namespace Esiur.Resource
|
|||||||
if (stores.TryGetValue(store, out list))
|
if (stores.TryGetValue(store, out list))
|
||||||
lock (((ICollection)list).SyncRoot)
|
lock (((ICollection)list).SyncRoot)
|
||||||
list.Add(resourceReference);
|
list.Add(resourceReference);
|
||||||
|
}
|
||||||
//stores[store].Add(resourceReference);
|
|
||||||
}
|
}
|
||||||
// assign self as a store (root store)
|
// assign self as a store (root store)
|
||||||
else if (resource is IStore)
|
else if (resource is IStore)
|
||||||
@ -723,8 +745,15 @@ namespace Esiur.Resource
|
|||||||
public static ResourceTemplate GetTemplate(Type type)
|
public static ResourceTemplate GetTemplate(Type type)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (!Codec.ImplementsInterface(type, typeof(IResource)))
|
||||||
|
return null;
|
||||||
|
|
||||||
var baseType = ResourceProxy.GetBaseType(type);
|
var baseType = ResourceProxy.GetBaseType(type);
|
||||||
|
|
||||||
|
if (baseType == typeof(IResource) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
|
||||||
// loaded ?
|
// loaded ?
|
||||||
foreach (var t in templates.Values)
|
foreach (var t in templates.Values)
|
||||||
if (t.ClassName == baseType.FullName)
|
if (t.ClassName == baseType.FullName)
|
||||||
@ -741,10 +770,10 @@ namespace Esiur.Resource
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="classId">Class Id.</param>
|
/// <param name="classId">Class Id.</param>
|
||||||
/// <returns>Resource template.</returns>
|
/// <returns>Resource template.</returns>
|
||||||
public static AsyncReply<ResourceTemplate> GetTemplate(Guid classId)
|
public static ResourceTemplate GetTemplate(Guid classId)
|
||||||
{
|
{
|
||||||
if (templates.ContainsKey(classId))
|
if (templates.ContainsKey(classId))
|
||||||
return new AsyncReply<ResourceTemplate>(templates[classId]);
|
return templates[classId];
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ namespace Esiur.Security.Membership
|
|||||||
AsyncReply<byte[]> GetToken(ulong tokenIndex, string domain);
|
AsyncReply<byte[]> GetToken(ulong tokenIndex, string domain);
|
||||||
AsyncReply<bool> Login(Session session);
|
AsyncReply<bool> Login(Session session);
|
||||||
AsyncReply<bool> Logout(Session session);
|
AsyncReply<bool> Logout(Session session);
|
||||||
|
bool GuestsAllowed { get; }
|
||||||
AsyncReply<string> TokenExists(ulong tokenIndex, string domain);
|
AsyncReply<string> TokenExists(ulong tokenIndex, string domain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ namespace Esiur.Security.Permissions
|
|||||||
AddChild,
|
AddChild,
|
||||||
RemoveChild,
|
RemoveChild,
|
||||||
Rename,
|
Rename,
|
||||||
ReceiveEvent
|
ReceiveEvent,
|
||||||
|
ViewTemplate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user