From 7c707637de4b7502710831867c0553c63439a5dd Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Sat, 20 Feb 2021 11:38:11 +0300 Subject: [PATCH] Added JSON --- Esiur.Stores.EntityCore/EntityStore.cs | 2 +- .../Esiur.Stores.EntityCore.csproj | 2 +- Esiur.Stores.EntityCore/EsiurExtensions.cs | 21 ++- Esiur.Stores.EntityCore/EsiurProxyRewrite.cs | 4 +- Esiur/Data/Codec.cs | 6 +- Esiur/Data/DataConverter.cs | 22 ++- Esiur/Data/ResourceJsonConverter.cs | 91 +++++++++++ Esiur/Data/Structure.cs | 2 + Esiur/Esiur.csproj | 12 +- Esiur/Misc/Global.cs | 27 ++++ Esiur/Resource/IResource.cs | 3 + Esiur/Resource/Instance.cs | 63 ++++---- Esiur/Resource/StoreGeneric.cs | 4 +- Esiur/Resource/Warehouse.cs | 143 ++++++++++++------ 14 files changed, 296 insertions(+), 106 deletions(-) create mode 100644 Esiur/Data/ResourceJsonConverter.cs diff --git a/Esiur.Stores.EntityCore/EntityStore.cs b/Esiur.Stores.EntityCore/EntityStore.cs index 0e0da55..24979df 100644 --- a/Esiur.Stores.EntityCore/EntityStore.cs +++ b/Esiur.Stores.EntityCore/EntityStore.cs @@ -79,7 +79,7 @@ namespace Esiur.Stores.EntityCore public AsyncReply Put(IResource resource) { if (resource is EntityStore) - return new AsyncReply(false); + return new AsyncReply(true); var type = ResourceProxy.GetBaseType(resource);//.GetType().; diff --git a/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj b/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj index 61f4312..561f5d1 100644 --- a/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj +++ b/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj @@ -12,7 +12,7 @@ - + diff --git a/Esiur.Stores.EntityCore/EsiurExtensions.cs b/Esiur.Stores.EntityCore/EsiurExtensions.cs index 6e2002a..75ad594 100644 --- a/Esiur.Stores.EntityCore/EsiurExtensions.cs +++ b/Esiur.Stores.EntityCore/EsiurExtensions.cs @@ -22,6 +22,7 @@ SOFTWARE. */ +using Esiur.Core; using Esiur.Resource; using Esiur.Security.Permissions; using Microsoft.EntityFrameworkCore; @@ -43,6 +44,9 @@ namespace Esiur.Stores.EntityCore //} public static T AddResource(this DbSet dbSet, object properties = null) where T : class, IResource + => AddResourceAsync(dbSet, properties).Wait(); + + public static async AsyncReply AddResourceAsync(this DbSet dbSet, object properties = null) where T : class, IResource { var store = dbSet.GetInfrastructure().GetService().FindExtension().Store; var manager = store.Instance.Managers.FirstOrDefault();// > 0 ? store.Instance.Managers.First() : null; @@ -51,28 +55,31 @@ namespace Esiur.Stores.EntityCore //var resource = dbSet.GetInfrastructure().CreateResource(properties); //var resource = Warehouse.New("", options.Store, null, null, null, properties); - var resource = Warehouse.New("", null, null, null, null, properties); + var resource = await Warehouse.New("", null, null, null, null, properties); var entity = dbSet.Add(resource); - entity.Context.SaveChanges(); + await entity.Context.SaveChangesAsync(); var id = store.TypesByType[typeof(T)].PrimaryKey.GetValue(resource); - Warehouse.Put(resource, id.ToString(), store, null, null, 0, manager); + await Warehouse.Put(resource, id.ToString(), store, null, null, 0, manager); return resource; } - public static T CreateResource(this IServiceProvider serviceProvider, object properties = null) where T : class, IResource + public static async AsyncReply CreateResourceAsync(this IServiceProvider serviceProvider, object properties = null) where T : class, IResource { var options = serviceProvider.GetService().FindExtension(); - var resource = Warehouse.New("", options.Store, null, null, null, properties); + var resource = await Warehouse.New("", options.Store, null, null, null, properties); resource.Instance.Managers.AddRange(options.Store.Instance.Managers.ToArray()); return resource; } + public static T CreateResource(this IServiceProvider serviceProvider, object properties = null) where T : class, IResource + => CreateResourceAsync(serviceProvider, properties).Wait(); + public static DbContextOptionsBuilder UseEsiur(this DbContextOptionsBuilder optionsBuilder, //DbContext context, string name = null, @@ -86,7 +93,7 @@ namespace Esiur.Stores.EntityCore if (extension == null) { - var store = Warehouse.New(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }); + var store = Warehouse.New(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }).Wait(); extension = new EsiurExtensionOptions(store); //store.Options = optionsBuilder; //store.DbContext = context; @@ -113,7 +120,7 @@ namespace Esiur.Stores.EntityCore if (extension == null) { - var store = Warehouse.New(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }); + var store = Warehouse.New(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }).Wait(); extension = new EsiurExtensionOptions(store); //store.Options = optionsBuilder; //store.Options = extension; diff --git a/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs b/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs index 73a10cc..f41a987 100644 --- a/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs +++ b/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs @@ -76,10 +76,10 @@ namespace Esiur.Stores.EntityCore return cache; // check if the object exists - var obj = Warehouse.New(entityType.ClrType) as EntityResource;//, "", options.Store, null, manager); + var obj = Warehouse.New(entityType.ClrType).Wait() as EntityResource;//, "", options.Store, null, manager); //obj._PrimaryId = id; options.Store.TypesByType[entityType.ClrType].PrimaryKey.SetValue(obj, id); - Warehouse.Put(obj, id.ToString(), options.Store, null, null, 0, manager); + Warehouse.Put(obj, id.ToString(), options.Store, null, null, 0, manager).Wait(); // obj.Instance.IntVal = id;//.Variables.Add("eid", id); diff --git a/Esiur/Data/Codec.cs b/Esiur/Data/Codec.cs index c7898d7..0b3da2a 100644 --- a/Esiur/Data/Codec.cs +++ b/Esiur/Data/Codec.cs @@ -36,6 +36,7 @@ using System.Reflection; using Esiur.Resource.Template; using System.Runtime.CompilerServices; using System.Collections; +using System.Dynamic; namespace Esiur.Data { @@ -239,7 +240,8 @@ namespace Esiur.Data /// Whether to include each item DataType /// If true, prepend the length as UInt32 at the beginning of the returned bytes array /// Array of bytes in the network byte order - public static byte[] ComposeStructure(Structure value, DistributedConnection connection, bool includeKeys = true, bool includeTypes = true, bool prependLength = false) + public static byte[] ComposeStructure(Structure value, DistributedConnection connection, + bool includeKeys = true, bool includeTypes = true, bool prependLength = false) { var rt = new BinaryList(); @@ -1269,7 +1271,7 @@ namespace Esiur.Data type = DataType.String; else if (t == typeof(DateTime)) type = DataType.DateTime; - else if (typeof(Structure).IsAssignableFrom(t)) + else if (typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject)) type = DataType.Structure; //else if (t == typeof(DistributedResource)) // type = DataType.DistributedResource; diff --git a/Esiur/Data/DataConverter.cs b/Esiur/Data/DataConverter.cs index aa551b4..79d9d9e 100644 --- a/Esiur/Data/DataConverter.cs +++ b/Esiur/Data/DataConverter.cs @@ -533,16 +533,22 @@ namespace Esiur.Data public static string ToHex(this byte[] ba, uint offset, uint length, string separator = " ") { - StringBuilder hex = new StringBuilder((int)length * 2); - for (var i = offset; i < offset + length; i++) - { - hex.AppendFormat("{0:x2}", ba[i]); - if (separator != null) - hex.Append(separator); - } + if (separator == null) + separator = ""; - return hex.ToString(); + return string.Join(separator, ba.Skip((int)offset).Take((int)length).Select(x => x.ToString("x2")).ToArray()); + + //StringBuilder hex = new StringBuilder((int)length * 2); + + //for (var i = offset; i < offset + length; i++) + //{ + // hex.AppendFormat("{0:x2}", ba[i]); + // if (separator != null) + // hex.Append(separator); + //} + + //return hex.ToString(); } public static byte[] FromHex(string hexString, string separator = " ") diff --git a/Esiur/Data/ResourceJsonConverter.cs b/Esiur/Data/ResourceJsonConverter.cs new file mode 100644 index 0000000..f65f30d --- /dev/null +++ b/Esiur/Data/ResourceJsonConverter.cs @@ -0,0 +1,91 @@ +using Esiur.Resource; +/* + +Copyright (c) 2017-2021 Ahmed Kh. Zamil + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Esiur.Data +{ + class ResourceJsonConverter : JsonConverter + { + public override IResource Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options) + { + return (IResource)JsonSerializer.Deserialize(ref reader,typeof(IResource), options); + } + + + public override void Write( + Utf8JsonWriter writer, + IResource resource, + JsonSerializerOptions options) + { + + writer.WriteStartObject(); + + foreach (var pt in resource.Instance.Template.Properties) + { + var rt = pt.Info.GetValue(resource, null); + writer.WritePropertyName(options.PropertyNamingPolicy?.ConvertName(pt.Name) ?? pt.Name); + JsonSerializer.Serialize(writer, rt, options); + } + + writer.WriteEndObject(); + + } + } + + + public class DoubleJsonConverter : JsonConverter + { + public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String && reader.GetString() == "NaN") + { + return double.NaN; + } + + return reader.GetDouble(); // JsonException thrown if reader.TokenType != JsonTokenType.Number + } + + public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options) + { + if (double.IsNaN(value)) + { + writer.WriteStringValue("NaN"); + } + else + { + writer.WriteNumberValue(value); + } + } + } + +} diff --git a/Esiur/Data/Structure.cs b/Esiur/Data/Structure.cs index b0f6dc0..b3977ef 100644 --- a/Esiur/Data/Structure.cs +++ b/Esiur/Data/Structure.cs @@ -85,6 +85,8 @@ namespace Esiur.Data rt.dic = source.dic; return rt; } + + public static explicit operator Structure(ExpandoObject obj) => FromDynamic(obj); public static Structure FromDynamic(ExpandoObject obj) { diff --git a/Esiur/Esiur.csproj b/Esiur/Esiur.csproj index 613d863..7f55a9f 100644 --- a/Esiur/Esiur.csproj +++ b/Esiur/Esiur.csproj @@ -1,13 +1,13 @@  - netstandard2.0 + netstandard2.1 Distributed Resources Platform Ahmed Kh. Zamil https://github.com/Esiur/Esiur-dotnet/blob/master/LICENSE http://www.esiur.com true - 1.5.0 + 1.5.1 https://github.com/esiur/esiur-dotnet Ahmed Kh. Zamil 1.3.1.0 @@ -28,6 +28,12 @@ True + + + + + + @@ -38,7 +44,6 @@ - @@ -57,6 +62,7 @@ + diff --git a/Esiur/Misc/Global.cs b/Esiur/Misc/Global.cs index 8374536..7923a71 100644 --- a/Esiur/Misc/Global.cs +++ b/Esiur/Misc/Global.cs @@ -38,6 +38,9 @@ using System.Linq; using Esiur.Core; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Text.Json; +using Esiur.Resource; +using System.Text.Json.Serialization; namespace Esiur.Misc { @@ -58,6 +61,30 @@ namespace Esiur.Misc public static event LogEvent SystemLog; + public static string ToJson(this IResource resource) + { + try + { + return JsonSerializer.Serialize(resource, Global.SerializeOptions); + }catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + return ""; + } + } + + public static JsonSerializerOptions SerializeOptions = new JsonSerializerOptions + { + ReferenceHandler = ReferenceHandler.Preserve, + WriteIndented = true, + Converters = + { + new ResourceJsonConverter(), + new DoubleJsonConverter() + } + }; + + public static string Version { get; }= FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; diff --git a/Esiur/Resource/IResource.cs b/Esiur/Resource/IResource.cs index 08fc127..da8a0b8 100644 --- a/Esiur/Resource/IResource.cs +++ b/Esiur/Resource/IResource.cs @@ -29,11 +29,14 @@ using System.Text; using Esiur.Data; using Esiur.Core; using System.ComponentModel; +using System.Text.Json.Serialization; namespace Esiur.Resource { public delegate bool QueryFilter(T value); + //[JsonConverter(typeof(ResourceJsonConverter))] + public interface IResource : IDestructible///, INotifyPropertyChanged { diff --git a/Esiur/Resource/Instance.cs b/Esiur/Resource/Instance.cs index cbf8c5d..dff37b6 100644 --- a/Esiur/Resource/Instance.cs +++ b/Esiur/Resource/Instance.cs @@ -13,6 +13,7 @@ using Esiur.Resource.Template; using Esiur.Security.Authority; using Esiur.Proxy; using Esiur.Core; +using System.Text.Json; namespace Esiur.Resource { @@ -20,7 +21,8 @@ namespace Esiur.Resource { string name; - // public int IntVal { get; set; } + // public int IntVal { get; set; } + WeakReference resource; IStore store; @@ -115,7 +117,7 @@ namespace Esiur.Resource return rt; - + /* var st = new Structure(); @@ -183,7 +185,7 @@ namespace Esiur.Resource if (at != null) if (at.Info.CanWrite) at.Info.SetValue(res, DC.CastConvert(kv.Value, at.Info.PropertyType)); - + } } @@ -426,6 +428,15 @@ namespace Esiur.Resource return true; } + public string ToJson() + { + IResource res; + if (resource.TryGetTarget(out res)) + return JsonSerializer.Serialize(res, Global.SerializeOptions); + else + return null; + } + /// /// Export all properties with ResourceProperty attributed as bytes array. /// @@ -436,28 +447,18 @@ namespace Esiur.Resource foreach (var pt in template.Properties) { - /* -#if NETSTANDARD - var pi = resource.GetType().GetTypeInfo().GetProperty(pt.Name); -#else - var pi = resource.GetType().GetProperty(pt.Name); -#endif -*/ + IResource res; - //if (pt.Serilize) - //{ - IResource res; - if (resource.TryGetTarget(out res)) - { - 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])); - } - //} + if (resource.TryGetTarget(out res)) + { + var rt = pt.Info.GetValue(res, null); + props.Add(new PropertyValue(rt, ages[pt.Index], modificationDates[pt.Index])); + } } return props.ToArray(); } + /* public bool Deserialize(byte[] data, uint offset, uint length) { @@ -712,7 +713,7 @@ namespace Esiur.Resource if (this.resource.TryGetTarget(out res)) { //if (!(store is null)) - return store.Children(res, name); + return store.Children(res, name); //else // return (res as IStore).Children(res, name); } @@ -824,14 +825,14 @@ namespace Esiur.Resource if (this.resource.TryGetTarget(out res)) { //return store.Applicable(res, session, action, member, inquirer); - + foreach (IPermissionsManager manager in managers) { var r = manager.Applicable(res, session, action, member, inquirer); if (r != Ruling.DontCare) return r; } - + } return Ruling.DontCare; @@ -873,14 +874,14 @@ namespace Esiur.Resource this.template = customTemplate; else this.template = Warehouse.GetTemplate(resource.GetType()); - - // set ages + + // set ages for (byte i = 0; i < template.Properties.Length; i++) { ages.Add(0); modificationDates.Add(DateTime.MinValue); } - + // connect events Type t = ResourceProxy.GetBaseType(resource); @@ -903,9 +904,9 @@ namespace Esiur.Resource 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(evt.Name, args); evt.Info.AddEventHandler(resource, proxyDelegate); @@ -920,7 +921,7 @@ namespace Esiur.Resource CustomResourceEventHanlder proxyDelegate = (issuer, receivers, args) => EmitCustomResourceEvent(issuer, receivers, evt.Name, args); evt.Info.AddEventHandler(resource, proxyDelegate); } - + /* else if (evt.EventHandlerType == typeof(CustomUsersEventHanlder)) @@ -959,7 +960,7 @@ namespace Esiur.Resource //IQueryable Children => store.GetChildren(this); - + /* * private void Children_OnRemoved(Instance parent, IResource value) { diff --git a/Esiur/Resource/StoreGeneric.cs b/Esiur/Resource/StoreGeneric.cs index 13e6e47..a3530bc 100644 --- a/Esiur/Resource/StoreGeneric.cs +++ b/Esiur/Resource/StoreGeneric.cs @@ -47,9 +47,9 @@ namespace Esiur.Resource public abstract AsyncReply Trigger(ResourceTrigger trigger); - public T New(string name = null, object attributes = null, object properties = null) + public async AsyncReply New(string name = null, object attributes = null, object properties = null) { - var resource = Warehouse.New(name, this, null, null, attributes, properties); + var resource = await Warehouse.New(name, this, null, null, attributes, properties); resource.Instance.Managers.AddRange(this.Instance.Managers.ToArray()); return resource; } diff --git a/Esiur/Resource/Warehouse.cs b/Esiur/Resource/Warehouse.cs index 19f409d..7a91a24 100644 --- a/Esiur/Resource/Warehouse.cs +++ b/Esiur/Resource/Warehouse.cs @@ -37,6 +37,7 @@ using System.Text.RegularExpressions; using Esiur.Misc; using System.Collections.Concurrent; using System.Collections; +using System.Data; namespace Esiur.Resource { @@ -62,7 +63,7 @@ namespace Esiur.Resource public static event StoreConnectedEvent StoreConnected; public static event StoreDisconnectedEvent StoreDisconnected; - public delegate IStore ProtocolInstance(string name, object properties); + public delegate AsyncReply ProtocolInstance(string name, object properties); public static KeyList Protocols { get; } = GetSupportedProtocols(); @@ -73,7 +74,7 @@ namespace Esiur.Resource static KeyList GetSupportedProtocols() { var rt = new KeyList(); - rt.Add("iip", (name, props) => Warehouse.New(name, null, null, null, props)); + rt.Add("iip", async (name, attributes) => await Warehouse.New(name, null, null, null, attributes)); return rt; } @@ -378,68 +379,100 @@ namespace Esiur.Resource /// /// /// Resource instance. - public static AsyncReply Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null) + public static async AsyncReply Get(string path, object attributes = null, IResource parent = null, IPermissionsManager manager = null) { - var rt = new AsyncReply(); + //var rt = new AsyncReply(); // Should we create a new store ? if (urlRegex.IsMatch(path)) { - //if (path.Contains("://")) - //{ var url = urlRegex.Split(path); - //var url = path.Split(new string[] { "://" }, 2, StringSplitOptions.None); - //var hostname = url[1].Split(new char[] { '/' }, 2)[0]; - //var pathname = string.Join("/", url[1].Split(new char[] { '/' }).Skip(1)); - if (Protocols.ContainsKey(url[1])) { + if (!warehouseIsOpen) + await Open(); + var handler = Protocols[url[1]]; + var store = await handler(url[2], attributes); - var store = handler(url[2], attributes); - - store.Trigger(ResourceTrigger.Open).Then(x => + try { - - warehouseIsOpen = true; - 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] != "") - store.Get(url[3]).Then(r => - { - rt.Trigger(r); - }).Error(e => - { - Warehouse.Remove(store); - rt.TriggerError(e); - }); + return await store.Get(url[3]); else - rt.Trigger(store); - }).Error(e => - { - rt.TriggerError(e); - //Warehouse.Remove(store); - }); + return store; + + } + catch (Exception ex) + { + Warehouse.Remove(store); + throw ex; + } - return rt; } + + + // store.Get(url[3]).Then(r => + // { + // rt.Trigger(r); + // }).Error(e => + // { + // Warehouse.Remove(store); + // rt.TriggerError(e); + // }); + // else + // rt.Trigger(store); + + // store.Trigger(ResourceTrigger.Open).Then(x => + // { + + // warehouseIsOpen = true; + // await Put(store, url[2], null, parent, null, 0, manager, attributes); + + // if (url[3].Length > 0 && url[3] != "") + // store.Get(url[3]).Then(r => + // { + // rt.Trigger(r); + // }).Error(e => + // { + // Warehouse.Remove(store); + // rt.TriggerError(e); + // }); + // else + // rt.Trigger(store); + // }).Error(e => + // { + // rt.TriggerError(e); + // //Warehouse.Remove(store); + // }); + + // return rt; + //} } - Query(path).Then(rs => - { - // rt.TriggerError(new Exception()); - if (rs != null && rs.Length > 0) - rt.Trigger(rs.First()); - else - rt.Trigger(null); - }); + //await Query(path).Then(rs => + //{ + // // rt.TriggerError(new Exception()); + // if (rs != null && rs.Length > 0) + // rt.Trigger(rs.First()); + // else + // rt.Trigger(null); + //}); - return rt; + //return rt; + var res = await Query(path); + + if (res.Length == 0) + return null; + else + return res.First(); } @@ -450,7 +483,7 @@ namespace Esiur.Resource /// Resource name. /// IStore that manages the resource. Can be null if the resource is a store. /// Parent resource. if not presented the store becomes the parent for the resource. - public static void Put(IResource resource, string name, IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) + public static async AsyncReply Put(IResource resource, string name, IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) { if (resource.Instance != null) throw new Exception("Resource has a store."); @@ -522,13 +555,14 @@ namespace Esiur.Resource //else - store.Put(resource); + if (!await store.Put(resource)) + return false; if (parent != null) { - parent.Instance.Store.AddChild(parent, resource); - store.AddParent(resource, parent); + await parent.Instance.Store.AddChild(parent, resource); + await store.AddParent(resource, parent); //store.AddChild(parent, resource); } @@ -542,11 +576,19 @@ namespace Esiur.Resource resources.TryAdd(resource.Instance.Id, resourceReference); if (warehouseIsOpen) - resource.Trigger(ResourceTrigger.Initialize); + { + await resource.Trigger(ResourceTrigger.Initialize); + if (resource is IStore) + await resource.Trigger(ResourceTrigger.Open); + + return true; + } + else + return true; } - public static IResource New(Type type, string name = null, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null) + public static async AsyncReply New(Type type, string name = null, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null) { type = ResourceProxy.GetProxy(type); @@ -608,16 +650,19 @@ namespace Esiur.Resource } if (store != null || parent != null || res is IStore) - Put(res, name, store, parent, null, 0, manager, attributes); + { + if (!await Put(res, name, store, parent, null, 0, manager, attributes)) + return null; + } return res; } - public static T New(string name, IStore store = null, IResource parent = null, IPermissionsManager manager = null, object attributes = null, object properties = null) + public static async AsyncReply New(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, properties); + return (T)(await New(typeof(T), name, store, parent, manager, attributes, properties)); } ///