2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-06-27 13:33:13 +00:00
This commit is contained in:
2020-02-26 03:14:22 +03:00
parent 7a21f6a928
commit fde1b1d8ad
39 changed files with 1108 additions and 502 deletions

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Resource
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Event)]
public class AnnotationAttribute : Attribute
{
public string Annotation { get; set; }
public AnnotationAttribute(string annotation)
{
this.Annotation = annotation;
}
}
}

View File

@ -31,10 +31,10 @@ namespace Esyur.Resource
{
[AttributeUsage(AttributeTargets.Property)]
public class ResourceAttribute : System.Attribute
public class AttributeAttribute : System.Attribute
{
public ResourceAttribute()
public AttributeAttribute()
{
}

View File

@ -176,7 +176,8 @@ namespace Esyur.Resource
if (at != null)
if (at.Info.CanWrite)
at.Info.SetValue(res, kv.Value);
at.Info.SetValue(res, DC.CastConvert(kv.Value, at.Info.PropertyType));
}
}
@ -442,7 +443,7 @@ namespace Esyur.Resource
IResource res;
if (resource.TryGetTarget(out res))
{
var rt = pt.Serilize ? pt.Info.GetValue(res, null) : null;
var rt = pt.Info.GetValue(res, null);// pt.Serilize ? pt.Info.GetValue(res, null) : null;
props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index]));
}
@ -546,13 +547,14 @@ namespace Esyur.Resource
ages[pt.Index] = instanceAge;
modificationDates[pt.Index] = now;
if (pt.Storage == StorageMode.NonVolatile)
{
store.Modify(res, pt.Name, value, ages[pt.Index], now);
}
else if (pt.Storage == StorageMode.Recordable)
if (pt.Recordable)
{
store.Record(res, pt.Name, value, ages[pt.Index], now);
}
else //if (pt.Storage == StorageMode.Recordable)
{
store.Modify(res, pt.Name, value, ages[pt.Index], now);
}
ResourceModified?.Invoke(res, pt.Name, value);
@ -839,7 +841,7 @@ namespace Esyur.Resource
this.store = store;
this.resource = new WeakReference<IResource>(resource);
this.id = id;
this.name = name;
this.name = name ?? "";
this.instanceAge = age;
//this.attributes = new KeyList<string, object>(this);
@ -875,30 +877,32 @@ namespace Esyur.Resource
var events = t.GetEvents(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
#endif
foreach (var evt in events)
foreach (var evt in template.Events)
{
//if (evt.EventHandlerType != typeof(ResourceEventHanlder))
// continue;
if (evt.EventHandlerType == typeof(ResourceEventHanlder))
if (evt.Info.EventHandlerType == typeof(ResourceEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
// var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
// if (ca.Length == 0)
// continue;
ResourceEventHanlder proxyDelegate = (args) => EmitResourceEvent(null, null, evt.Name, args);
evt.AddEventHandler(resource, proxyDelegate);
evt.Info.AddEventHandler(resource, proxyDelegate);
}
else if (evt.EventHandlerType == typeof(CustomResourceEventHanlder))
else if (evt.Info.EventHandlerType == typeof(CustomResourceEventHanlder))
{
var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
if (ca.Length == 0)
continue;
//var ca = (ResourceEvent[])evt.GetCustomAttributes(typeof(ResourceEvent), true);
//if (ca.Length == 0)
// continue;
CustomResourceEventHanlder proxyDelegate = (issuer, receivers, args) => EmitResourceEvent(issuer, receivers, evt.Name, args);
evt.AddEventHandler(resource, proxyDelegate);
evt.Info.AddEventHandler(resource, proxyDelegate);
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Resource
{
public class PrivateAttribute:Attribute
{
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Resource
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Event | AttributeTargets.Class)]
public class PublicAttribute : Attribute
{
// public StorageMode Storage { get; set; }
//public bool Serialize { get; set; }
public PublicAttribute()//StorageMode storage = StorageMode.NonVolatile, bool serialize = true)
{
// Storage = storage;
//Serialize = serialize;
}
}
}

View File

@ -47,7 +47,7 @@ namespace Esyur.Resource
return new AsyncReply<bool>(true);
}
public virtual bool Create()
protected virtual bool Create()
{
return true;
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esyur.Resource
{
[AttributeUsage(AttributeTargets.Property)]
public class StorageAttribute:Attribute
{
public StorageMode Mode { get; set; }
public StorageAttribute(StorageMode mode)
{
Mode = mode;
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Text;
using Esyur.Core;
using Esyur.Data;
using Esyur.Resource.Template;
namespace Esyur.Resource
{
public abstract class Store<T> : IStore where T:IResource
{
public Instance Instance { get; set; }
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> AddChild(IResource parent, IResource child);
public abstract AsyncReply<bool> AddParent(IResource child, IResource parent);
public abstract AsyncBag<T1> Children<T1>(IResource resource, string name) where T1 : IResource;
public virtual void Destroy()
{
OnDestroy?.Invoke(this);
}
public abstract AsyncReply<IResource> Get(string path);
public abstract AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> GetRecord(IResource resource, DateTime fromDate, DateTime toDate);
public abstract string Link(IResource resource);
public abstract bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime);
public abstract AsyncBag<T1> Parents<T1>(IResource resource, string name) where T1 : IResource;
public abstract AsyncReply<bool> Put(IResource resource);
public abstract bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime);
public abstract bool Remove(IResource resource);
public abstract AsyncReply<bool> RemoveChild(IResource parent, IResource child);
public abstract AsyncReply<bool> RemoveParent(IResource child, IResource parent);
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public T New(string name = null, object attributes = null, object properties = null)
{
var resource = Warehouse.New<T>(name, this, null, null, attributes, properties);
resource.Instance.Managers.AddRange(this.Instance.Managers.ToArray());
return resource;
}
}
}

View File

@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
@ -15,6 +16,8 @@ namespace Esyur.Resource.Template
set;
}
public EventInfo Info { get; set; }
public override byte[] Compose()
{
var name = base.Compose();
@ -39,7 +42,7 @@ namespace Esyur.Resource.Template
}
public EventTemplate(ResourceTemplate template, byte index, string name, string expansion)
public EventTemplate(ResourceTemplate template, byte index, string name, string expansion = null)
:base(template, MemberType.Property, index, name)
{
this.Expansion = expansion;

View File

@ -45,7 +45,7 @@ namespace Esyur.Resource.Template
}
public FunctionTemplate(ResourceTemplate template, byte index, string name,bool isVoid, string expansion)
public FunctionTemplate(ResourceTemplate template, byte index, string name,bool isVoid, string expansion = null)
:base(template, MemberType.Property, index, name)
{
this.IsVoid = isVoid;

View File

@ -24,10 +24,12 @@ namespace Esyur.Resource.Template
set;
}
/*
public bool Serilize
{
get;set;
}
*/
//bool ReadOnly;
//IIPTypes::DataType ReturnType;
public PropertyPermission Permission {
@ -35,18 +37,19 @@ namespace Esyur.Resource.Template
set;
}
/*
public bool Recordable
{
get;
set;
}*/
}
public StorageMode Storage
/*
public PropertyType Mode
{
get;
set;
}
}*/
public string ReadExpansion
{
@ -71,7 +74,7 @@ namespace Esyur.Resource.Template
public override byte[] Compose()
{
var name = base.Compose();
var pv = ((byte)(Permission) << 1) | (Storage == StorageMode.Recordable ? 1 : 0);
var pv = ((byte)(Permission) << 1) | (Recordable ? 1 : 0);
if (WriteExpansion != null && ReadExpansion != null)
{
@ -117,11 +120,11 @@ namespace Esyur.Resource.Template
.ToArray();
}
public PropertyTemplate(ResourceTemplate template, byte index, string name, string read, string write, StorageMode storage)
public PropertyTemplate(ResourceTemplate template, byte index, string name, string read = null, string write = null, bool recordable = false)
:base(template, MemberType.Property, index, name)
{
//this.Recordable = recordable;
this.Storage = storage;
this.Recordable = recordable;
//this.Storage = storage;
this.ReadExpansion = read;
this.WriteExpansion = write;
}

View File

@ -8,6 +8,7 @@ using Esyur.Data;
using Esyur.Core;
using System.Security.Cryptography;
using Esyur.Proxy;
using Esyur.Net.IIP;
namespace Esyur.Resource.Template
{
@ -159,52 +160,87 @@ namespace Esyur.Resource.Template
MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
#endif
//byte currentIndex = 0;
bool classIsPublic = type.GetCustomAttribute<PublicAttribute>() != null;
byte i = 0;
foreach (var pi in propsInfo)
if (classIsPublic)
{
var rp = pi.GetCustomAttribute<ResourceProperty>(true);
if (rp != null)
{
var pt = new PropertyTemplate(this, i++, pi.Name, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
pt.Info = pi;
pt.Serilize = rp.Serialize;
properties.Add(pt);
}
var ra = pi.GetCustomAttribute<ResourceAttribute>(true);
if (ra != null)
{
var at = new AttributeTemplate(this, i++, pi.Name);
at.Info = pi;
attributes.Add(at);
}
}
i = 0;
foreach (var ei in eventsInfo)
else
{
var es = ei.GetCustomAttributes<ResourceEvent>(true).ToArray();
if (es.Length > 0)
foreach (var pi in propsInfo)
{
var et = new EventTemplate(this, i++, ei.Name, es[0].Expansion);
events.Add(et);
var publicAttr = pi.GetCustomAttribute<PublicAttribute>(true);
if (publicAttr != null)
{
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
var pt = new PropertyTemplate(this, i++, pi.Name);//, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
if (storageAttr != null)
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
if (annotationAttr != null)
pt.ReadExpansion = annotationAttr.Annotation;
else
pt.ReadExpansion = pi.PropertyType.Name;
pt.Info = pi;
//pt.Serilize = publicAttr.Serialize;
properties.Add(pt);
}
else
{
var attributeAttr = pi.GetCustomAttribute<AttributeAttribute>(true);
if (attributeAttr != null)
{
var at = new AttributeTemplate(this, 0, pi.Name);
at.Info = pi;
attributes.Add(at);
}
}
}
}
i = 0;
foreach (MethodInfo mi in methodsInfo)
{
var fs = mi.GetCustomAttributes<ResourceFunction>(true).ToArray();
if (fs.Length > 0)
i = 0;
foreach (var ei in eventsInfo)
{
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void), fs[0].Expansion);
functions.Add(ft);
var publicAttr = ei.GetCustomAttribute<PublicAttribute>(true);
if (publicAttr != null)
{
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
var et = new EventTemplate(this, i++, ei.Name);
et.Info = ei;
if (annotationAttr != null)
et.Expansion = annotationAttr.Annotation;
events.Add(et);
}
}
i = 0;
foreach (MethodInfo mi in methodsInfo)
{
var publicAttr = mi.GetCustomAttribute<PublicAttribute>(true);
if (publicAttr != null)
{
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void));
if (annotationAttr != null)
ft.Expansion = annotationAttr.Annotation;
else
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x=>x.ParameterType != typeof(DistributedConnection)).Select(x=> "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
functions.Add(ft);
}
}
}
@ -323,7 +359,7 @@ namespace Esyur.Resource.Template
offset += cs;
}
var pt = new PropertyTemplate(od, propertyIndex++, name, readExpansion, writeExpansion, recordable ? StorageMode.Recordable : StorageMode.Volatile);
var pt = new PropertyTemplate(od, propertyIndex++, name, readExpansion, writeExpansion, recordable);
od.properties.Add(pt);
}

View File

@ -35,6 +35,7 @@ using System.Threading.Tasks;
using Esyur.Net.IIP;
using System.Text.RegularExpressions;
using Esyur.Misc;
using System.Collections.Concurrent;
namespace Esyur.Resource
{
@ -43,8 +44,11 @@ namespace Esyur.Resource
{
//static byte prefixCounter;
static AutoList<IStore, Instance> stores = new AutoList<IStore, Instance>(null);
static Dictionary<uint, WeakReference<IResource>> resources = new Dictionary<uint, WeakReference<IResource>>();
//static AutoList<IStore, Instance> stores = new AutoList<IStore, Instance>(null);
static ConcurrentDictionary<uint, WeakReference<IResource>> resources = new ConcurrentDictionary<uint, WeakReference<IResource>>();
static ConcurrentDictionary<IStore, List<WeakReference<IResource>>> stores = new ConcurrentDictionary<IStore, List<WeakReference<IResource>>>();
static uint resourceCounter = 0;
static KeyList<Guid, ResourceTemplate> templates = new KeyList<Guid, ResourceTemplate>();
@ -61,7 +65,7 @@ namespace Esyur.Resource
private static Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)");
private static object resourcesLock = new object();
//private static object resourcesLock = new object();
static KeyList<string, Func<IStore>> getSupportedProtocols()
{
@ -78,8 +82,8 @@ namespace Esyur.Resource
public static IStore GetStore(string name)
{
foreach (var s in stores)
if (s.Instance.Name == name)
return s as IStore;
if (s.Key.Instance.Name == name)
return s.Key;
return null;
}
@ -113,22 +117,28 @@ namespace Esyur.Resource
{
warehouseIsOpen = true;
var resSnap = resources.Select(x => {
IResource r;
var resSnap = resources.Select(x =>
{
IResource r;
if (x.Value.TryGetTarget(out r))
return r;
else
return null;
}).Where(r=>r!=null).ToArray();
}).Where(r => r != null).ToArray();
foreach (var r in resSnap)
{
//IResource r;
//if (rk.Value.TryGetTarget(out r))
//{
var rt = await r.Trigger(ResourceTrigger.Initialize);
if (!rt)
return false;
var rt = await r.Trigger(ResourceTrigger.Initialize);
//if (!rt)
// return false;
if (!rt)
{
Console.WriteLine($"Resource failed at Initialize {r.Instance.Name} [{r.Instance.Template.ClassName}]");
}
//}
}
@ -137,9 +147,12 @@ namespace Esyur.Resource
//IResource r;
//if (rk.Value.TryGetTarget(out r))
//{
var rt = await r.Trigger(ResourceTrigger.SystemInitialized);
if (!rt)
return false;
var rt = await r.Trigger(ResourceTrigger.SystemInitialized);
if (!rt)
{
Console.WriteLine($"Resource failed at SystemInitialized {r.Instance.Name} [{r.Instance.Template.ClassName}]");
}
//return false;
//}
}
@ -217,7 +230,7 @@ namespace Esyur.Resource
}
foreach (var store in stores)
bag.Add(store.Trigger(ResourceTrigger.Terminate));
bag.Add(store.Key.Trigger(ResourceTrigger.Terminate));
foreach (var resource in resources.Values)
@ -232,7 +245,7 @@ namespace Esyur.Resource
foreach (var store in stores)
bag.Add(store.Trigger(ResourceTrigger.SystemTerminated));
bag.Add(store.Key.Trigger(ResourceTrigger.SystemTerminated));
bag.Seal();
@ -318,7 +331,7 @@ namespace Esyur.Resource
var p = path.Trim().Split('/');
IResource resource;
foreach (var store in stores)
foreach (var store in stores.Keys)
if (p[0] == store.Instance.Name)
{
@ -433,19 +446,26 @@ namespace Esyur.Resource
if (resource.Instance != null)
throw new Exception("Resource has a store.");
var resourceReference = new WeakReference<IResource>(resource);
if (store == null)
{
// assign parent as a store
if (parent is IStore)
{
store = (IStore)parent;
stores[store].Add(resourceReference);
}
// assign parent's store as a store
else if (parent != null)
{
store = parent.Instance.Store;
stores[store].Add(resourceReference);
}
// assign self as a store (root store)
else if (resource is IStore)
{
store = (IStore)resource;
stores.Add(resource as IStore);
}
else
throw new Exception("Can't find a store for the resource.");
@ -475,10 +495,13 @@ namespace Esyur.Resource
if (resource is IStore)
{
stores.TryAdd(resource as IStore, new List<WeakReference<IResource>>());
StoreConnected?.Invoke(resource as IStore, name);
}
//else
store.Put(resource);
@ -493,15 +516,17 @@ namespace Esyur.Resource
var t = resource.GetType();
Global.Counters["T-" + t.Namespace + "." + t.Name]++;
lock (resourcesLock)
resources.Add(resource.Instance.Id, new WeakReference<IResource>(resource));
//var wr = new WeakReference<IResource>(resource);
//lock (resourcesLock)
resources.TryAdd(resource.Instance.Id, resourceReference);
if (warehouseIsOpen)
resource.Trigger(ResourceTrigger.Initialize);
}
public static IResource New(Type type, string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, Structure attributes = null, Structure arguments = null, Structure properties = null)
public static IResource New(Type type, string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null)
{
type = ResourceProxy.GetProxy(type);
@ -539,9 +564,12 @@ namespace Esyur.Resource
*/
var res = Activator.CreateInstance(type) as IResource;
if (properties != null)
{
foreach (var p in properties)
var ps = Structure.FromObject(properties);
foreach (var p in ps)
{
var pi = type.GetProperty(p.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
if (pi != null)
@ -556,10 +584,10 @@ namespace Esyur.Resource
}
public static T New<T>(string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, Structure attributes = null, Structure arguments = null, Structure properties = null)
public static T New<T>(string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null)
where T : IResource
{
return (T)New(typeof(T), name, store, parent, manager, attributes, arguments, properties);
return (T)New(typeof(T), name, store, parent, manager, attributes, properties);
}
/// <summary>
@ -619,31 +647,45 @@ namespace Esyur.Resource
public static bool Remove(IResource resource)
{
if (resource.Instance == null)
return false;
//lock (resourcesLock)
//{
WeakReference<IResource> resourceReference;
if (resources.ContainsKey(resource.Instance.Id))
lock(resourcesLock)
resources.Remove(resource.Instance.Id);
resources.TryRemove(resource.Instance.Id, out resourceReference);
else
return false;
//}
if (resource != resource.Instance.Store)
stores[resource.Instance.Store].Remove(resourceReference);
if (resource is IStore)
{
stores.Remove(resource as IStore);
var store = resource as IStore;
WeakReference<IResource>[] toBeRemoved;
List<WeakReference<IResource>> toBeRemoved;// = stores[store];
stores.TryRemove(store, out toBeRemoved);
//lock (resourcesLock)
//{
// // remove all objects associated with the store
// toBeRemoved = resources.Values.Where(x =>
// {
// IResource r;
// if (x.TryGetTarget(out r))
// return r.Instance.Store == resource;
// else
// return false;
// }).ToArray();
//}
lock (resourcesLock)
{
// remove all objects associated with the store
toBeRemoved = resources.Values.Where(x =>
{
IResource r;
return x.TryGetTarget(out r) && r.Instance.Store == resource;
}).ToArray();
}
foreach (var o in toBeRemoved)
{