2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2026-04-29 06:48:41 +00:00
This commit is contained in:
2026-04-05 12:35:27 +03:00
parent 44983d7784
commit c7d095ea96
17 changed files with 546 additions and 732 deletions
+230 -227
View File
@@ -267,263 +267,266 @@ namespace Esiur.Data
// case TRUIdentifier. }
//}
private static Dictionary<Type, Tru> _cache = new Dictionary<Type, Tru>();
private static Dictionary<Type, Tru> cache = new Dictionary<Type, Tru>();
private static object cacheLook = new object();
public static Tru? FromType(Type type)
{
if (type == null)
return new Tru(TruIdentifier.Void, true);
if (_cache.ContainsKey(type))
return _cache[type];
var nullable = false;
var nullType = System.Nullable.GetUnderlyingType(type);
if (nullType != null)
lock (cacheLook)
{
type = nullType;
nullable = true;
}
if (cache.ContainsKey(type))
return cache[type];
Tru? tru = null;
var nullable = false;
if (type == typeof(IResource))
{
return new Tru(TruIdentifier.Resource, nullable);
}
else if (type == typeof(IRecord) || type == typeof(Record))
{
return new Tru(TruIdentifier.Record, nullable);
}
else if (type == typeof(Map<object, object>)
|| type == typeof(Dictionary<object, object>))
{
return new Tru(TruIdentifier.Map, nullable);
}
else if (Codec.ImplementsInterface(type, typeof(IResource)))
{
tru = new Tru(
TruIdentifier.TypedResource,
nullable,
TypeDef.GetTypeUUID(type)
);
}
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
{
tru = new Tru(
TruIdentifier.TypedRecord,
nullable,
TypeDef.GetTypeUUID(type)
);
}
else if (type.IsGenericType)
{
var genericType = type.GetGenericTypeDefinition();
var nullType = System.Nullable.GetUnderlyingType(type);
if (genericType == typeof(List<>)
|| genericType == typeof(VarList<>)
|| genericType == typeof(IList<>))
if (nullType != null)
{
var args = type.GetGenericArguments();
if (args[0] == typeof(object))
type = nullType;
nullable = true;
}
Tru? tru = null;
if (type == typeof(IResource))
{
return new Tru(TruIdentifier.Resource, nullable);
}
else if (type == typeof(IRecord) || type == typeof(Record))
{
return new Tru(TruIdentifier.Record, nullable);
}
else if (type == typeof(Map<object, object>)
|| type == typeof(Dictionary<object, object>))
{
return new Tru(TruIdentifier.Map, nullable);
}
else if (Codec.ImplementsInterface(type, typeof(IResource)))
{
tru = new Tru(
TruIdentifier.TypedResource,
nullable,
TypeDef.GetTypeUUID(type)
);
}
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
{
tru = new Tru(
TruIdentifier.TypedRecord,
nullable,
TypeDef.GetTypeUUID(type)
);
}
else if (type.IsGenericType)
{
var genericType = type.GetGenericTypeDefinition();
if (genericType == typeof(List<>)
|| genericType == typeof(VarList<>)
|| genericType == typeof(IList<>))
{
tru = new Tru(TruIdentifier.List, nullable);
var args = type.GetGenericArguments();
if (args[0] == typeof(object))
{
tru = new Tru(TruIdentifier.List, nullable);
}
else
{
var subType = FromType(args[0]);
if (subType == null) // unrecongnized type
return null;
tru = new Tru(TruIdentifier.TypedList, nullable, null,
new Tru[] { subType });
}
}
else if (genericType == typeof(Map<,>)
|| genericType == typeof(Dictionary<,>))
{
var args = type.GetGenericArguments();
if (args[0] == typeof(object) && args[1] == typeof(object))
{
tru = new Tru(TruIdentifier.Map, nullable);
}
else
{
var subType1 = FromType(args[0]);
if (subType1 == null)
return null;
var subType2 = FromType(args[1]);
if (subType2 == null)
return null;
tru = new Tru(TruIdentifier.TypedMap, nullable, null,
new Tru[] { subType1, subType2 });
}
}
else if (genericType == typeof(ResourceLink<>))
{
var args = type.GetGenericArguments();
return FromType(args[0]);
}
else if (genericType == typeof(ValueTuple<,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple2, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple3, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple4, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple5, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple6, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple7, nullable, null, subTypes);
}
else
return null;
}
else if (type.IsArray)
{
var elementType = type.GetElementType();
if (elementType == typeof(object))
tru = new Tru(TruIdentifier.List, nullable);
else
{
var subType = FromType(args[0]);
if (subType == null) // unrecongnized type
return null;
var subType = FromType(elementType);
if (subType == null)
return null;
tru = new Tru(TruIdentifier.TypedList, nullable, null,
new Tru[] { subType });
}
}
else if (genericType == typeof(Map<,>)
|| genericType == typeof(Dictionary<,>))
else if (type.IsEnum)
{
var args = type.GetGenericArguments();
if (args[0] == typeof(object) && args[1] == typeof(object))
{
tru = new Tru(TruIdentifier.Map, nullable);
}
else
{
var subType1 = FromType(args[0]);
if (subType1 == null)
return null;
var subType2 = FromType(args[1]);
if (subType2 == null)
return null;
tru = new Tru(TruIdentifier.TypedMap, nullable, null,
new Tru[] { subType1, subType2 });
}
tru = new Tru(TruIdentifier.Enum, nullable, TypeDef.GetTypeUUID(type));
}
else if (genericType == typeof(ResourceLink<>))
else if (type.IsInterface)
{
var args = type.GetGenericArguments();
return FromType(args[0]);
return null; // other interfaces are not supported
}
else if (genericType == typeof(ValueTuple<,>))
//else if (typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => TRUIdentifier.Structure)
//{
//}
if (tru != null)
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple2, nullable, null, subTypes);
cache.Add(type, tru);
return tru;
}
else if (genericType == typeof(ValueTuple<,,>))
// last check
return type switch
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple3, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple4, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple5, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple6, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new Tru[args.Length];
for (var i = 0; i < args.Length; i++)
{
var t = FromType(args[i]);
if (t == null)
return null;
subTypes[i] = t;
}
tru = new Tru(TruIdentifier.Tuple7, nullable, null, subTypes);
}
else
return null;
_ when type == typeof(void) => new Tru(TruIdentifier.Void, nullable),
_ when type == typeof(object) => new Tru(TruIdentifier.Dynamic, nullable),
_ when type == typeof(bool) => new Tru(TruIdentifier.Bool, nullable),
_ when type == typeof(char) => new Tru(TruIdentifier.Char, nullable),
_ when type == typeof(byte) => new Tru(TruIdentifier.UInt8, nullable),
_ when type == typeof(sbyte) => new Tru(TruIdentifier.Int8, nullable),
_ when type == typeof(short) => new Tru(TruIdentifier.Int16, nullable),
_ when type == typeof(ushort) => new Tru(TruIdentifier.UInt16, nullable),
_ when type == typeof(int) => new Tru(TruIdentifier.Int32, nullable),
_ when type == typeof(uint) => new Tru(TruIdentifier.UInt32, nullable),
_ when type == typeof(long) => new Tru(TruIdentifier.Int64, nullable),
_ when type == typeof(ulong) => new Tru(TruIdentifier.UInt64, nullable),
_ when type == typeof(float) => new Tru(TruIdentifier.Float32, nullable),
_ when type == typeof(double) => new Tru(TruIdentifier.Float64, nullable),
_ when type == typeof(decimal) => new Tru(TruIdentifier.Decimal, nullable),
_ when type == typeof(string) => new Tru(TruIdentifier.String, nullable),
_ when type == typeof(DateTime) => new Tru(TruIdentifier.DateTime, nullable),
_ when type == typeof(ResourceLink) => new Tru(TruIdentifier.Resource, nullable),
_ => null
};
}
else if (type.IsArray)
{
var elementType = type.GetElementType();
if (elementType == typeof(object))
tru = new Tru(TruIdentifier.List, nullable);
else
{
var subType = FromType(elementType);
if (subType == null)
return null;
tru = new Tru(TruIdentifier.TypedList, nullable, null,
new Tru[] { subType });
}
}
else if (type.IsEnum)
{
tru = new Tru(TruIdentifier.Enum, nullable, TypeDef.GetTypeUUID(type));
}
else if (type.IsInterface)
{
return null; // other interfaces are not supported
}
//else if (typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => TRUIdentifier.Structure)
//{
//}
if (tru != null)
{
_cache.Add(type, tru);
return tru;
}
// last check
return type switch
{
_ when type == typeof(void) => new Tru(TruIdentifier.Void, nullable),
_ when type == typeof(object) => new Tru(TruIdentifier.Dynamic, nullable),
_ when type == typeof(bool) => new Tru(TruIdentifier.Bool, nullable),
_ when type == typeof(char) => new Tru(TruIdentifier.Char, nullable),
_ when type == typeof(byte) => new Tru(TruIdentifier.UInt8, nullable),
_ when type == typeof(sbyte) => new Tru(TruIdentifier.Int8, nullable),
_ when type == typeof(short) => new Tru(TruIdentifier.Int16, nullable),
_ when type == typeof(ushort) => new Tru(TruIdentifier.UInt16, nullable),
_ when type == typeof(int) => new Tru(TruIdentifier.Int32, nullable),
_ when type == typeof(uint) => new Tru(TruIdentifier.UInt32, nullable),
_ when type == typeof(long) => new Tru(TruIdentifier.Int64, nullable),
_ when type == typeof(ulong) => new Tru(TruIdentifier.UInt64, nullable),
_ when type == typeof(float) => new Tru(TruIdentifier.Float32, nullable),
_ when type == typeof(double) => new Tru(TruIdentifier.Float64, nullable),
_ when type == typeof(decimal) => new Tru(TruIdentifier.Decimal, nullable),
_ when type == typeof(string) => new Tru(TruIdentifier.String, nullable),
_ when type == typeof(DateTime) => new Tru(TruIdentifier.DateTime, nullable),
_ when type == typeof(ResourceLink) => new Tru(TruIdentifier.Resource, nullable),
_ => null
};
}
public Tru(TruIdentifier identifier, bool nullable, Uuid? uuid = null, Tru[]? subTypes = null)
+5 -5
View File
@@ -12,12 +12,12 @@ namespace Esiur.Net.Packets
Stream = 0x2,
// Error
PermissionError = 0x81,
ExecutionError = 0x82,
PermissionError = 0x4,
ExecutionError = 0x5,
// Partial
Progress = 0x10,
Chunk = 0x11,
Warning = 0x12
Progress = 0x8,
Chunk = 0x9,
Warning = 0xA
}
}
+177 -160
View File
@@ -57,9 +57,11 @@ partial class EpConnection
Dictionary<Uuid, TypeDef> typeDefs = new Dictionary<Uuid, TypeDef>();
object typeDefsLock = new object();
KeyList<uint, AsyncReply> requests = new KeyList<uint, AsyncReply>();
volatile uint callbackCounter = 0;
volatile int callbackCounter = 0;
Dictionary<IResource, List<byte>> subscriptions = new Dictionary<IResource, List<byte>>();
@@ -73,15 +75,18 @@ partial class EpConnection
/// <summary>
/// Send IIP request.
/// Send EP request.
/// </summary>
/// <param name="action">Packet action.</param>
/// <param name="args">Arguments to send.</param>
/// <returns></returns>
///
AsyncReply SendRequest(EpPacketRequest action, params object[] args)
{
var reply = new AsyncReply();
var c = callbackCounter++; // avoid thread racing
var c = (uint)Interlocked.Increment(ref callbackCounter);
//callbackCounter++; // avoid thread racing
requests.Add(c, reply);
if (args.Length == 0)
@@ -112,7 +117,7 @@ partial class EpConnection
}
/// <summary>
/// Send IIP notification.
/// Send EP notification.
/// </summary>
/// <param name="action">Packet action.</param>
/// <param name="args">Arguments to send.</param>
@@ -343,7 +348,7 @@ partial class EpConnection
var args = DataDeserializer.ListParser(dataType, Instance.Warehouse)
as object[];
var errorCode = (ushort)args[0];
var errorCode =Convert.ToUInt16( args[0]);
var errorMsg = (string)args[1];
req.TriggerError(new AsyncException(type, errorCode, errorMsg));
@@ -1721,60 +1726,66 @@ partial class EpConnection
/// <returns>TypeSchema.</returns>
public AsyncReply<TypeDef> GetTypeDefById(Uuid typeId)
{
if (typeDefs.ContainsKey(typeId))
return new AsyncReply<TypeDef>(typeDefs[typeId]);
else if (typeDefsByIdRequests.ContainsKey(typeId))
return typeDefsByIdRequests[typeId];
lock (typeDefsLock)
{
if (typeDefs.ContainsKey(typeId))
return new AsyncReply<TypeDef>(typeDefs[typeId]);
else if (typeDefsByIdRequests.ContainsKey(typeId))
return typeDefsByIdRequests[typeId];
var reply = new AsyncReply<TypeDef>();
typeDefsByIdRequests.Add(typeId, reply);
var reply = new AsyncReply<TypeDef>();
typeDefsByIdRequests.Add(typeId, reply);
SendRequest(EpPacketRequest.TypeDefById, typeId)
.Then((result) =>
{
var tt = TypeDef.Parse((byte[])result);
typeDefsByIdRequests.Remove(typeId);
typeDefs.Add(tt.Id, tt);
Instance.Warehouse.RegisterTypeDef(tt);
reply.Trigger(tt);
SendRequest(EpPacketRequest.TypeDefById, typeId)
.Then((result) =>
{
var tt = TypeDef.Parse((byte[])result);
typeDefsByIdRequests.Remove(typeId);
typeDefs.Add(tt.Id, tt);
Instance.Warehouse.RegisterTypeDef(tt);
reply.Trigger(tt);
}).Error((ex) =>
{
reply.TriggerError(ex);
});
}).Error((ex) =>
{
reply.TriggerError(ex);
});
return reply;
return reply;
}
}
public AsyncReply<TypeDef> GetTypeDefByName(string typeName)
{
var typeDef = typeDefs.Values.FirstOrDefault(x => x.Name == typeName);
if (typeDef != null)
return new AsyncReply<TypeDef>(typeDef);
lock (typeDefsLock)
{
var typeDef = typeDefs.Values.FirstOrDefault(x => x.Name == typeName);
if (typeDef != null)
return new AsyncReply<TypeDef>(typeDef);
if (typeDefsByNameRequests.ContainsKey(typeName))
return typeDefsByNameRequests[typeName];
if (typeDefsByNameRequests.ContainsKey(typeName))
return typeDefsByNameRequests[typeName];
var reply = new AsyncReply<TypeDef>();
typeDefsByNameRequests.Add(typeName, reply);
var reply = new AsyncReply<TypeDef>();
typeDefsByNameRequests.Add(typeName, reply);
SendRequest(EpPacketRequest.TypeDefByName, typeName)
.Then((result) =>
{
var tt = TypeDef.Parse((byte[])result);
SendRequest(EpPacketRequest.TypeDefByName, typeName)
.Then((result) =>
{
var tt = TypeDef.Parse((byte[])result);
typeDefsByNameRequests.Remove(typeName);
typeDefs.Add(tt.Id, tt);
Instance.Warehouse.RegisterTypeDef(tt);
reply.Trigger(tt);
}).Error((ex) =>
{
reply.TriggerError(ex);
});
typeDefsByNameRequests.Remove(typeName);
typeDefs.Add(tt.Id, tt);
Instance.Warehouse.RegisterTypeDef(tt);
reply.Trigger(tt);
}).Error((ex) =>
{
reply.TriggerError(ex);
});
return reply;
return reply;
}
}
// IStore interface
@@ -1846,156 +1857,162 @@ partial class EpConnection
/// </summary>
/// <param name="id">Resource Id</param>
/// <returns>DistributedResource</returns>
///
object fetchLock = new object();
public AsyncReply<EpResource> Fetch(uint id, uint[] requestSequence)
{
//lock (fetchLock)
//{
EpResource resource = null;
EpResource resource = null;
attachedResources[id]?.TryGetTarget(out resource);
attachedResources[id]?.TryGetTarget(out resource);
if (resource != null)
return new AsyncReply<EpResource>(resource);
resource = neededResources[id];
var requestInfo = resourceRequests[id];
if (requestInfo != null)
{
if (resource != null && (requestSequence?.Contains(id) ?? false))
{
// dead lock avoidance for loop reference.
if (resource != null)
return new AsyncReply<EpResource>(resource);
}
else if (resource != null && requestInfo.RequestSequence.Contains(id))
resource = neededResources[id];
var requestInfo = resourceRequests[id];
if (requestInfo != null)
{
// dead lock avoidance for dependent reference.
if (resource != null && (requestSequence?.Contains(id) ?? false))
{
// dead lock avoidance for loop reference.
return new AsyncReply<EpResource>(resource);
}
else if (resource != null && requestInfo.RequestSequence.Contains(id))
{
// dead lock avoidance for dependent reference.
return new AsyncReply<EpResource>(resource);
}
else
{
return requestInfo.Reply;
}
}
else if (resource != null && !resource.DistributedResourceSuspended)
{
// @REVIEW: this should never happen
Global.Log("DCON", LogType.Error, "Resource not moved to attached.");
return new AsyncReply<EpResource>(resource);
}
else
{
return requestInfo.Reply;
}
}
else if (resource != null && !resource.DistributedResourceSuspended)
{
// @REVIEW: this should never happen
Global.Log("DCON", LogType.Error, "Resource not moved to attached.");
return new AsyncReply<EpResource>(resource);
}
var newSequence = requestSequence != null ? requestSequence.Concat(new uint[] { id }).ToArray() : new uint[] { id };
var newSequence = requestSequence != null ? requestSequence.Concat(new uint[] { id }).ToArray() : new uint[] { id };
var reply = new AsyncReply<EpResource>();
resourceRequests.Add(id, new EpResourceAttachRequestInfo(reply, newSequence));
var reply = new AsyncReply<EpResource>();
resourceRequests.Add(id, new EpResourceAttachRequestInfo(reply, newSequence));
SendRequest(EpPacketRequest.AttachResource, id)
.Then((result) =>
{
if (result == null)
SendRequest(EpPacketRequest.AttachResource, id)
.Then((result) =>
{
reply.TriggerError(new AsyncException(ErrorType.Management,
(ushort)ExceptionCode.ResourceNotFound, "Null response"));
return;
}
if (result == null)
{
reply.TriggerError(new AsyncException(ErrorType.Management,
(ushort)ExceptionCode.ResourceNotFound, "Null response"));
return;
}
// TypeId, Age, Link, Hops, PropertyValue[]
var args = (object[])result;
var typeId = (Uuid)args[0];
var age = Convert.ToUInt64(args[1]);
var link = (string)args[2];
var hops = (byte)args[3];
var pvData = (byte[])args[4];
// TypeId, Age, Link, Hops, PropertyValue[]
var args = (object[])result;
var typeId = (Uuid)args[0];
var age = Convert.ToUInt64(args[1]);
var link = (string)args[2];
var hops = (byte)args[3];
var pvData = (byte[])args[4];
EpResource dr;
TypeDef typeDef = null;
EpResource dr;
TypeDef typeDef = null;
if (resource == null)
{
typeDef = Instance.Warehouse.GetTypeDefById(typeId, TypeDefKind.Resource);
if (typeDef?.DefinedType != null && typeDef.IsWrapper)
dr = Activator.CreateInstance(typeDef.DefinedType, this, id, Convert.ToUInt64(args[1]), (string)args[2]) as EpResource;
if (resource == null)
{
typeDef = Instance.Warehouse.GetTypeDefById(typeId, TypeDefKind.Resource);
if (typeDef?.DefinedType != null && typeDef.IsWrapper)
dr = Activator.CreateInstance(typeDef.DefinedType, this, id, Convert.ToUInt64(args[1]), (string)args[2]) as EpResource;
else
dr = new EpResource(this, id, Convert.ToUInt64(args[1]), (string)args[2]);
}
else
dr = new EpResource(this, id, Convert.ToUInt64(args[1]), (string)args[2]);
}
else
{
dr = resource;
typeDef = resource.Instance.Definition;
}
var initResource = (EpResource ok) =>
{
var parsedReply = DataDeserializer.PropertyValueArrayParserAsync(pvData, 0, (uint)pvData.Length, this, newSequence);// Codec.proper (content, 0, this, newSequence, transmissionType);
parsedReply.Then(results =>
{
var pvs = results as PropertyValue[];
//var pvs = new List<PropertyValue>();
//for (var i = 0; i < ar.Length; i += 3)
// pvs.Add(new PropertyValue(ar[i + 2], Convert.ToUInt64(ar[i]), (DateTime)ar[i + 1]));
dr._Attach(pvs);
resourceRequests.Remove(id);
// move from needed to attached.
neededResources.Remove(id);
attachedResources[id] = new WeakReference<EpResource>(dr);
reply.Trigger(dr);
}).Error(ex => reply.TriggerError(ex));
dr = resource;
typeDef = resource.Instance.Definition;
}
};
if (typeDef == null)
{
GetTypeDefById(typeId).Then((tmp) =>
var initResource = (EpResource ok) =>
{
var parsedReply = DataDeserializer.PropertyValueArrayParserAsync(pvData, 0, (uint)pvData.Length, this, newSequence);// Codec.proper (content, 0, this, newSequence, transmissionType);
parsedReply.Then(results =>
{
var pvs = results as PropertyValue[];
//var pvs = new List<PropertyValue>();
//for (var i = 0; i < ar.Length; i += 3)
// pvs.Add(new PropertyValue(ar[i + 2], Convert.ToUInt64(ar[i]), (DateTime)ar[i + 1]));
dr._Attach(pvs);
resourceRequests.Remove(id);
// move from needed to attached.
neededResources.Remove(id);
attachedResources[id] = new WeakReference<EpResource>(dr);
reply.Trigger(dr);
}).Error(ex => reply.TriggerError(ex));
};
if (typeDef == null)
{
GetTypeDefById(typeId).Then((tmp) =>
{
// typeId, ResourceAge, ResourceLink, Content
if (resource == null)
{
dr.ResourceDefinition = tmp;
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr)
.Then(initResource)
.Error(ex => reply.TriggerError(ex));
}
else
{
initResource(resource);
}
}).Error((ex) =>
{
reply.TriggerError(ex);
});
}
else
{
// typeId, ResourceAge, ResourceLink, Content
if (resource == null)
{
dr.ResourceDefinition = tmp;
dr.ResourceDefinition = typeDef;
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr)
.Then(initResource)
.Error(ex => reply.TriggerError(ex));
.Then(initResource).Error((ex) => reply.TriggerError(ex));
}
else
{
initResource(resource);
}
}).Error((ex) =>
{
reply.TriggerError(ex);
});
}
else
}
}).Error((ex) =>
{
if (resource == null)
{
Instance.Warehouse.Put(this.Instance.Link + "/" + id.ToString(), dr)
.Then(initResource).Error((ex) => reply.TriggerError(ex));
}
else
{
initResource(resource);
}
}
}).Error((ex) =>
{
reply.TriggerError(ex);
});
reply.TriggerError(ex);
});
return reply;
return reply;
//}
}
+8 -27
View File
@@ -117,30 +117,6 @@ namespace Esiur.Proxy
}
}
// var code = @$"using Esiur.Resource;
//using Esiur.Core;
//#nullable enable
//namespace {ci.ClassSymbol.ContainingNamespace.ToDisplayString()} {{
//";
// if (IsInterfaceImplemented(ci, classes))
// code += $"public partial class {ci.Name} {{\r\n";
// else
// {
// code +=
//$@" public partial class {ci.Name} : IResource {{
// public virtual Instance? Instance {{ get; set; }}
// public virtual event DestroyedEvent? OnDestroy;
// public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
//";
// if (!ci.HasTrigger)
// code += "\tpublic virtual AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);\r\n\r\n";
// }
foreach (var f in ci.Fields)
{
var givenName = f.GetAttributes().FirstOrDefault(x => x.AttributeClass?.Name == "ExportAttribute")?.ConstructorArguments.FirstOrDefault().Value as string;
@@ -156,12 +132,17 @@ namespace Esiur.Proxy
if (f.Type.Name.StartsWith("ResourceEventHandler") || f.Type.Name.StartsWith("CustomResourceEventHandler"))
{
code.AppendLine($"public event {f.Type} {pn};");
code.AppendLine($"\tpublic event {f.Type} {pn};");
}
else
{
code.AppendLine($"\t{attrs}\r\n\t public {f.Type} {pn} {{ \r\n\t\t get => {fn}; \r\n\t\t set {{ \r\n\t\t this.{fn} = value; \r\n\t\t Instance?.Modified(); \r\n\t\t}}\r\n\t}}\r\n");
code.AppendLine($"\tpublic {f.Type} {pn} {{");
code.AppendLine($"\t\t get => {fn};");
code.AppendLine($"\t\t set {{");
code.AppendLine($"\t\t this.{fn} = value;");
code.AppendLine($"\t\t Instance?.Modified();");
code.AppendLine($"\t\t}}");
code.AppendLine($"\t}}");
}
}
+38 -35
View File
@@ -11,6 +11,7 @@ namespace Esiur.Proxy;
public static class ResourceProxy
{
static Dictionary<Type, Type> cache = new Dictionary<Type, Type>();
static object cacheLock = new object();
#if NETSTANDARD
static MethodInfo modifyMethod = typeof(Instance).GetTypeInfo().GetMethod("Modified");
@@ -48,33 +49,34 @@ public static class ResourceProxy
public static Type GetProxy(Type type)
{
if (cache.ContainsKey(type))
return cache[type];
// check if the type was made with code generation
if (type.GetCustomAttribute<ResourceAttribute>(false) != null)
lock (cacheLock)
{
cache.Add(type, type);
return type;
}
if (cache.ContainsKey(type))
return cache[type];
if (!Codec.ImplementsInterface(type, typeof(IResource)))
{
cache.Add(type, type);
return type;
}
// check if the type was made with code generation
if (type.GetCustomAttribute<ResourceAttribute>(false) != null)
{
cache.Add(type, type);
return type;
}
if (!Codec.ImplementsInterface(type, typeof(IResource)))
{
cache.Add(type, type);
return type;
}
#if NETSTANDARD
var typeInfo = type.GetTypeInfo();
var typeInfo = type.GetTypeInfo();
if (typeInfo.IsSealed || typeInfo.IsAbstract)
throw new Exception("Sealed/Abastract classes can't be proxied.");
if (typeInfo.IsSealed || typeInfo.IsAbstract)
throw new Exception("Sealed/Abastract classes can't be proxied.");
var props = from p in typeInfo.GetProperties(BindingFlags.Instance | BindingFlags.Public)
where p.CanWrite && p.SetMethod.IsVirtual && !p.SetMethod.IsFinal &&
p.GetCustomAttribute<ExportAttribute>(false) != null
select p;
var props = from p in typeInfo.GetProperties(BindingFlags.Instance | BindingFlags.Public)
where p.CanWrite && p.SetMethod.IsVirtual && !p.SetMethod.IsFinal &&
p.GetCustomAttribute<ExportAttribute>(false) != null
select p;
#else
if (type.IsSealed)
@@ -86,33 +88,34 @@ public static class ResourceProxy
select p;
#endif
var assemblyName = new AssemblyName("Esiur.Proxy.T." + type.Assembly.GetName().Name);// type.Namespace);
assemblyName.Version = type.Assembly.GetName().Version;
assemblyName.CultureInfo = type.Assembly.GetName().CultureInfo;
//assemblyName.SetPublicKeyToken(null);
var assemblyName = new AssemblyName("Esiur.Proxy.T." + type.Assembly.GetName().Name);// type.Namespace);
assemblyName.Version = type.Assembly.GetName().Version;
assemblyName.CultureInfo = type.Assembly.GetName().CultureInfo;
//assemblyName.SetPublicKeyToken(null);
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
var typeName = "Esiur.Proxy.T." + type.FullName;// Assembly.CreateQualifiedName(assemblyName.FullName, "Esiur.Proxy.T." + type.FullName);
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
var typeName = "Esiur.Proxy.T." + type.FullName;// Assembly.CreateQualifiedName(assemblyName.FullName, "Esiur.Proxy.T." + type.FullName);
var typeBuilder = moduleBuilder.DefineType(typeName,
TypeAttributes.Public | TypeAttributes.Class, type);
var typeBuilder = moduleBuilder.DefineType(typeName,
TypeAttributes.Public | TypeAttributes.Class, type);
foreach (PropertyInfo propertyInfo in props)
CreateProperty(propertyInfo, typeBuilder, type);
foreach (PropertyInfo propertyInfo in props)
CreateProperty(propertyInfo, typeBuilder, type);
#if NETSTANDARD
var t = typeBuilder.CreateTypeInfo().AsType();
cache.Add(type, t);
return t;
var t = typeBuilder.CreateTypeInfo().AsType();
cache.Add(type, t);
return t;
#else
var t = typeBuilder.CreateType();
cache.Add(type, t);
return t;
#endif
}
}
public static Type GetProxy<T>()
+1 -1
View File
@@ -753,7 +753,7 @@ public class Instance
}
else
{
this.definition = Warehouse.GetTypeDefByType(resource.GetType());
this.definition = warehouse.GetTypeDefByType(resource.GetType());
}
// set ages
+20 -11
View File
@@ -67,6 +67,8 @@ public class Warehouse
[TypeDefKind.Enum] = new KeyList<Uuid, TypeDef>(),
};
object typeDefsLock = new object();
bool warehouseIsOpen = false;
public delegate void StoreEvent(IStore store);
@@ -508,10 +510,13 @@ public class Warehouse
/// <param name="typeDef">Resource type definition.</param>
public void RegisterTypeDef(TypeDef typeDef)
{
if (typeDefs[typeDef.Kind].ContainsKey(typeDef.Id))
throw new Exception($"TypeDef with same class Id already exists. {typeDefs[typeDef.Kind][typeDef.Id].Name} -> {typeDef.Name}");
lock (typeDefsLock)
{
if (typeDefs[typeDef.Kind].ContainsKey(typeDef.Id))
throw new Exception($"TypeDef with same class Id already exists. {typeDefs[typeDef.Kind][typeDef.Id].Name} -> {typeDef.Name}");
typeDefs[typeDef.Kind][typeDef.Id] = typeDef;
typeDefs[typeDef.Kind][typeDef.Id] = typeDef;
}
}
@@ -522,9 +527,11 @@ public class Warehouse
/// <returns>Resource TypeDef.</returns>
public TypeDef GetTypeDefByType(Type type)
{
if (!(type.IsClass || type.IsEnum))
return null;
var baseType = ResourceProxy.GetBaseType(type);
if (baseType == typeof(IResource)
@@ -541,15 +548,17 @@ public class Warehouse
else
return null;
var typeDef = typeDefs[typeDefKind].Values.FirstOrDefault(x => x.DefinedType == baseType);
if (typeDef != null)
lock (typeDefsLock)
{
var typeDef = typeDefs[typeDefKind].Values.FirstOrDefault(x => x.DefinedType == baseType);
if (typeDef != null)
return typeDef;
// create new TypeDef for type
typeDef = new TypeDef(baseType, this);
TypeDef.GetDependencies(typeDef, this);
return typeDef;
// create new TypeDef for type
typeDef = new TypeDef(baseType, this);
TypeDef.GetDependencies(typeDef, this);
return typeDef;
}
}
/// <summary>