mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-06-26 13:03:13 +00:00
1.6.1
This commit is contained in:
@ -40,7 +40,7 @@ namespace Esiur.Stores.EntityCore
|
||||
//internal object _PrimaryId;
|
||||
|
||||
public event DestroyedEvent OnDestroy;
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
//public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
[NotMapped]
|
||||
public Instance Instance { get; set; }
|
||||
@ -66,7 +66,7 @@ namespace Esiur.Stores.EntityCore
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,31 +45,25 @@ namespace Esiur.Stores.EntityCore
|
||||
Dictionary<Type, Dictionary<object, WeakReference>> DB = new Dictionary<Type, Dictionary<object, WeakReference>>();
|
||||
object DBLock = new object();
|
||||
|
||||
internal struct TypeInfo
|
||||
{
|
||||
public string Name;
|
||||
public IEntityType Type;
|
||||
public PropertyInfo PrimaryKey;
|
||||
}
|
||||
Dictionary<string, EntityTypeInfo> TypesByName = new Dictionary<string, EntityTypeInfo>();
|
||||
internal Dictionary<Type, EntityTypeInfo> TypesByType = new Dictionary<Type, EntityTypeInfo>();
|
||||
|
||||
Dictionary<string, TypeInfo> TypesByName = new Dictionary<string, TypeInfo>();
|
||||
internal Dictionary<Type, TypeInfo> TypesByType = new Dictionary<Type, TypeInfo>();
|
||||
[Attribute]
|
||||
public Func<DbContext> Getter { get; set; }
|
||||
|
||||
|
||||
|
||||
bool Loaded;
|
||||
|
||||
public AsyncReply<IResource> Get(string path)
|
||||
{
|
||||
var p = path.Split('/');
|
||||
var ti = TypesByName[p[0]];
|
||||
var id = Convert.ChangeType(p[1], ti.PrimaryKey.PropertyType);// Convert.ToInt32();
|
||||
var id = Convert.ChangeType(p[1], ti.PrimaryKey.PropertyType);
|
||||
|
||||
|
||||
var db = DbContextProvider();
|
||||
// Get db
|
||||
var db = Getter();
|
||||
var res = db.Find(ti.Type.ClrType, id);
|
||||
var ent = db.Entry(res);
|
||||
|
||||
// load navigation properties
|
||||
var ent = db.Entry(res);
|
||||
foreach (var rf in ent.References)
|
||||
rf.Load();
|
||||
|
||||
@ -78,12 +72,11 @@ namespace Esiur.Stores.EntityCore
|
||||
|
||||
public AsyncReply<bool> Put(IResource resource)
|
||||
{
|
||||
if (resource is EntityStore)
|
||||
if (resource == this)
|
||||
return new AsyncReply<bool>(true);
|
||||
|
||||
var type = ResourceProxy.GetBaseType(resource);//.GetType().;
|
||||
var type = ResourceProxy.GetBaseType(resource);
|
||||
|
||||
//var eid = (resource as EntityResource)._PrimaryId;// (int)resource.Instance.Variables["eid"];
|
||||
|
||||
var eid = TypesByType[type].PrimaryKey.GetValue(resource);
|
||||
|
||||
@ -112,11 +105,12 @@ namespace Esiur.Stores.EntityCore
|
||||
}
|
||||
}
|
||||
|
||||
[Attribute]
|
||||
public Func<DbContext> DbContextProvider { get; set; }
|
||||
|
||||
[Attribute]
|
||||
public DbContextOptionsBuilder Options { get; set; }
|
||||
|
||||
//public T CreateDB()
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
//DbContext dbContext;
|
||||
//[Attribute]
|
||||
@ -195,13 +189,17 @@ namespace Esiur.Stores.EntityCore
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal DbContextOptions Options { get; set; }
|
||||
|
||||
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||
{
|
||||
if (trigger == ResourceTrigger.Initialize)// SystemInitialized && DbContext != null)
|
||||
{
|
||||
|
||||
if (DbContextProvider == null)
|
||||
DbContextProvider = () => Activator.CreateInstance(Options.Options.ContextType, Options.Options) as DbContext;
|
||||
if (Getter == null)
|
||||
throw new Exception("Getter is not set for the store.");
|
||||
// DbContextProvider = () => Activator.CreateInstance(Options.Options.ContextType, Options.Options) as DbContext;
|
||||
|
||||
|
||||
ReloadModel();
|
||||
}
|
||||
@ -209,21 +207,23 @@ namespace Esiur.Stores.EntityCore
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
|
||||
public void ReloadModel()
|
||||
void ReloadModel()
|
||||
{
|
||||
|
||||
TypesByName.Clear();
|
||||
TypesByType.Clear();
|
||||
|
||||
var context = DbContextProvider();// Activator.CreateInstance(Options.Options.ContextType, Options.Options) as DbContext;
|
||||
var context = Getter();
|
||||
|
||||
var types = context.Model.GetEntityTypes();
|
||||
foreach (var t in types)
|
||||
{
|
||||
var ti = new TypeInfo()
|
||||
var ti = new EntityTypeInfo()
|
||||
{
|
||||
Name = t.ClrType.Name,
|
||||
PrimaryKey = t.FindPrimaryKey().Properties.FirstOrDefault()?.PropertyInfo,
|
||||
Type = t
|
||||
Type = t,
|
||||
//Getter = getter
|
||||
};
|
||||
|
||||
TypesByName.Add(t.ClrType.Name, ti);
|
||||
@ -236,7 +236,7 @@ namespace Esiur.Stores.EntityCore
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
17
Esiur.Stores.EntityCore/EntityTypeInfo.cs
Normal file
17
Esiur.Stores.EntityCore/EntityTypeInfo.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Stores.EntityCore
|
||||
{
|
||||
struct EntityTypeInfo
|
||||
{
|
||||
public string Name;
|
||||
public IEntityType Type;
|
||||
public PropertyInfo PrimaryKey;
|
||||
// public Func<DbContext> Getter;
|
||||
}
|
||||
}
|
@ -9,10 +9,11 @@
|
||||
<Product>Esiur Entity Framework Extension</Product>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageId>Esiur.Stores.EntityCore</PackageId>
|
||||
<Version>1.0.2</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.6" />
|
||||
<PackageReference Include="System.Collections" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -34,10 +34,11 @@ using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using System.Reflection;
|
||||
using Esiur.Proxy;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Esiur.Stores.EntityCore
|
||||
{
|
||||
public class EsiurExtensionOptions : IDbContextOptionsExtension
|
||||
public class EsiurExtensionOptions : IDbContextOptionsExtension
|
||||
{
|
||||
|
||||
//public Dictionary<Type, PropertyInfo> Cache { get; } = new Dictionary<Type, PropertyInfo>();
|
||||
|
@ -23,6 +23,9 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
using Esiur.Core;
|
||||
using Esiur.Data;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Proxy;
|
||||
using Esiur.Resource;
|
||||
using Esiur.Security.Permissions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -31,6 +34,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Stores.EntityCore
|
||||
@ -43,49 +47,108 @@ namespace Esiur.Stores.EntityCore
|
||||
|
||||
//}
|
||||
|
||||
public static T AddResource<T>(this DbSet<T> dbSet, object properties = null) where T : class, IResource
|
||||
=> AddResourceAsync(dbSet, properties).Wait();
|
||||
public static T AddResource<T>(this DbSet<T> dbSet, T resource) where T : class, IResource
|
||||
=> AddResourceAsync(dbSet, resource).Wait();
|
||||
|
||||
public static async AsyncReply<T> AddResourceAsync<T>(this DbSet<T> dbSet, object properties = null) where T : class, IResource
|
||||
public static async AsyncReply<T> AddResourceAsync<T>(this DbSet<T> dbSet, T resource) where T : class, IResource
|
||||
{
|
||||
var store = dbSet.GetInfrastructure().GetService<IDbContextOptions>().FindExtension<EsiurExtensionOptions>().Store;
|
||||
|
||||
|
||||
var manager = store.Instance.Managers.FirstOrDefault();// > 0 ? store.Instance.Managers.First() : null;
|
||||
|
||||
//var db = dbSet.GetService<ICurrentDbContext>().Context;
|
||||
|
||||
//var resource = dbSet.GetInfrastructure().CreateResource<T>(properties);
|
||||
//var resource = Warehouse.New<T>("", options.Store, null, null, null, properties);
|
||||
var resource = await Warehouse.New<T>("", null, null, null, null, properties);
|
||||
var entity = dbSet.Add(resource);
|
||||
|
||||
var resType = typeof(T);
|
||||
var proxyType = ResourceProxy.GetProxy(resType);
|
||||
|
||||
|
||||
IResource res;
|
||||
|
||||
if (proxyType == resType)
|
||||
{
|
||||
res = resource;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = Activator.CreateInstance(proxyType) as IResource;
|
||||
var ps = Structure.FromObject(resource);
|
||||
|
||||
foreach (var p in ps)
|
||||
{
|
||||
|
||||
var mi = resType.GetMember(p.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (mi != null)
|
||||
{
|
||||
if (mi is PropertyInfo)
|
||||
{
|
||||
var pi = mi as PropertyInfo;
|
||||
if (pi.CanWrite)
|
||||
{
|
||||
try
|
||||
{
|
||||
pi.SetValue(res, p.Value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Global.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mi is FieldInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
(mi as FieldInfo).SetValue(res, p.Value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Global.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//await Warehouse.Put<T>("", null, null, null, null, properties);
|
||||
var entity = dbSet.Add((T)res);
|
||||
await entity.Context.SaveChangesAsync();
|
||||
|
||||
|
||||
var id = store.TypesByType[typeof(T)].PrimaryKey.GetValue(resource);
|
||||
|
||||
await Warehouse.Put(resource, id.ToString(), store, null, null, 0, manager);
|
||||
await Warehouse.Put(id.ToString(), res, store, null, null, 0, manager);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
public static async AsyncReply<T> CreateResourceAsync<T>(this IServiceProvider serviceProvider, object properties = null) where T : class, IResource
|
||||
{
|
||||
var options = serviceProvider.GetService<IDbContextOptions>().FindExtension<EsiurExtensionOptions>();
|
||||
//public static async AsyncReply<T> CreateResourceAsync<T>(this IServiceProvider serviceProvider, T properties = null) where T : class, IResource
|
||||
//{
|
||||
// var options = serviceProvider.GetService<IDbContextOptions>().FindExtension<EsiurExtensionOptions<T>>();
|
||||
|
||||
var resource = await Warehouse.New<T>("", options.Store, null, null, null, properties);
|
||||
// var resource = await Warehouse.New<T>("", options.Store, null, null, null, properties);
|
||||
|
||||
resource.Instance.Managers.AddRange(options.Store.Instance.Managers.ToArray());
|
||||
// resource.Instance.Managers.AddRange(options.Store.Instance.Managers.ToArray());
|
||||
|
||||
return resource;
|
||||
}
|
||||
// return resource;
|
||||
//}
|
||||
|
||||
public static T CreateResource<T>(this IServiceProvider serviceProvider, object properties = null) where T : class, IResource
|
||||
=> CreateResourceAsync<T>(serviceProvider, properties).Wait();
|
||||
//public static T CreateResource<T>(this IServiceProvider serviceProvider, object properties = null) where T : class, IResource
|
||||
// => CreateResourceAsync<T>(serviceProvider, properties).Wait();
|
||||
|
||||
public static DbContextOptionsBuilder UseEsiur(this DbContextOptionsBuilder optionsBuilder,
|
||||
//DbContext context,
|
||||
string name = null,
|
||||
IResource parent = null,
|
||||
IPermissionsManager manager = null,
|
||||
Func<DbContext> dbContextProvider = null
|
||||
EntityStore store,
|
||||
Func<DbContext> getter = null
|
||||
|
||||
//IServiceCollection services = null
|
||||
//string name = null,
|
||||
//IResource parent = null,
|
||||
//IPermissionsManager manager = null,
|
||||
//Func<DbContext> dbContextProvider = null
|
||||
)
|
||||
{
|
||||
var extension = optionsBuilder.Options.FindExtension<EsiurExtensionOptions>();
|
||||
@ -93,10 +156,9 @@ namespace Esiur.Stores.EntityCore
|
||||
if (extension == null)
|
||||
{
|
||||
|
||||
var store = Warehouse.New<EntityStore>(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }).Wait();
|
||||
//var store = Warehouse.New<EntityStore>(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }).Wait();
|
||||
store.Options = optionsBuilder.Options;
|
||||
extension = new EsiurExtensionOptions(store);
|
||||
//store.Options = optionsBuilder;
|
||||
//store.DbContext = context;
|
||||
}
|
||||
|
||||
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||
@ -105,34 +167,34 @@ namespace Esiur.Stores.EntityCore
|
||||
|
||||
}
|
||||
|
||||
public static DbContextOptionsBuilder<TContext> UseEsiur<TContext>(
|
||||
this DbContextOptionsBuilder<TContext> optionsBuilder,
|
||||
//DbContext context,
|
||||
string name = null,
|
||||
IResource parent = null,
|
||||
IPermissionsManager manager = null,
|
||||
Func<DbContext> dbContextProvider = null)
|
||||
where TContext : DbContext
|
||||
{
|
||||
//public static DbContextOptionsBuilder<TContext> UseEsiur<TContext>(
|
||||
// this DbContextOptionsBuilder<TContext> optionsBuilder,
|
||||
// //DbContext context,
|
||||
// string name = null,
|
||||
// IResource parent = null,
|
||||
// IPermissionsManager manager = null,
|
||||
// Func<DbContext> dbContextProvider = null)
|
||||
// where TContext : DbContext
|
||||
//{
|
||||
|
||||
|
||||
var extension = optionsBuilder.Options.FindExtension<EsiurExtensionOptions>();
|
||||
// var extension = optionsBuilder.Options.FindExtension<EsiurExtensionOptions>();
|
||||
|
||||
if (extension == null)
|
||||
{
|
||||
var store = Warehouse.New<EntityStore>(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }).Wait();
|
||||
extension = new EsiurExtensionOptions(store);
|
||||
//store.Options = optionsBuilder;
|
||||
//store.Options = extension;
|
||||
//store.DbContext = context;
|
||||
}
|
||||
// if (extension == null)
|
||||
// {
|
||||
// var store = Warehouse.New<EntityStore>(name, null, parent, manager, new { Options = optionsBuilder, DbContextProvider = dbContextProvider }).Wait();
|
||||
// extension = new EsiurExtensionOptions(store);
|
||||
// //store.Options = optionsBuilder;
|
||||
// //store.Options = extension;
|
||||
// //store.DbContext = context;
|
||||
// }
|
||||
|
||||
|
||||
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||
// ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||
|
||||
return optionsBuilder;
|
||||
// return optionsBuilder;
|
||||
|
||||
}
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
|
||||
namespace Esiur.Stores.EntityCore
|
||||
{
|
||||
public class EsiurProxyRewrite : IModelFinalizingConvention
|
||||
public class EsiurProxyRewrite : IModelFinalizingConvention
|
||||
{
|
||||
private static readonly MethodInfo _createInstance
|
||||
= typeof(EsiurProxyRewrite).GetTypeInfo().GetDeclaredMethod(nameof(EsiurProxyRewrite.CreateInstance));
|
||||
@ -79,7 +79,7 @@ namespace Esiur.Stores.EntityCore
|
||||
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).Wait();
|
||||
Warehouse.Put(id.ToString(), obj, options.Store, null, null, 0, manager).Wait();
|
||||
|
||||
// obj.Instance.IntVal = id;//.Variables.Add("eid", id);
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/esiur/esiur-dotnet/</RepositoryUrl>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Version>1.4.0</Version>
|
||||
<Version>1.4.1</Version>
|
||||
<PackageId>Esiur.Stores.MongoDB</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace Esiur.Core
|
||||
public T GetResult()
|
||||
{
|
||||
if (exception != null)
|
||||
throw exception;
|
||||
throw exception;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,7 @@ namespace Esiur.Core
|
||||
// }
|
||||
}
|
||||
|
||||
public void Trigger(object result)
|
||||
public AsyncReply Trigger(object result)
|
||||
{
|
||||
lock (asyncLock)
|
||||
{
|
||||
@ -202,7 +202,7 @@ namespace Esiur.Core
|
||||
Console.WriteLine($"AsyncReply: {Id} Trigger");
|
||||
|
||||
if (resultReady)
|
||||
return;
|
||||
return this;
|
||||
|
||||
this.result = result;
|
||||
|
||||
@ -219,14 +219,16 @@ namespace Esiur.Core
|
||||
Console.WriteLine($"AsyncReply: {Id} Trigger ended");
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void TriggerError(Exception exception)
|
||||
public AsyncReply TriggerError(Exception exception)
|
||||
{
|
||||
//timeout?.Dispose();
|
||||
|
||||
if (resultReady)
|
||||
return;
|
||||
return this;
|
||||
|
||||
if (exception is AsyncException)
|
||||
this.exception = exception as AsyncException;
|
||||
@ -242,9 +244,10 @@ namespace Esiur.Core
|
||||
|
||||
mutex?.Set();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void TriggerProgress(ProgressType type, int value, int max)
|
||||
public AsyncReply TriggerProgress(ProgressType type, int value, int max)
|
||||
{
|
||||
//timeout?.Dispose();
|
||||
|
||||
@ -254,10 +257,12 @@ namespace Esiur.Core
|
||||
cb(type, value, max);
|
||||
|
||||
//}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public void TriggerChunk(object value)
|
||||
public AsyncReply TriggerChunk(object value)
|
||||
{
|
||||
|
||||
//timeout?.Dispose();
|
||||
@ -269,6 +274,8 @@ namespace Esiur.Core
|
||||
cb(value);
|
||||
|
||||
//}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncAwaiter GetAwaiter()
|
||||
|
@ -36,6 +36,10 @@ namespace Esiur.Core
|
||||
SetPropertyDenied,
|
||||
ReadOnlyProperty,
|
||||
GeneralFailure,
|
||||
AddToStoreFailed
|
||||
AddToStoreFailed,
|
||||
NotAttached,
|
||||
AlreadyListened,
|
||||
AlreadyUnlistened,
|
||||
NotListenable
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Esiur.Resource;
|
||||
using Esiur.Net.IIP;
|
||||
using Esiur.Resource;
|
||||
/*
|
||||
|
||||
Copyright (c) 2017-2021 Ahmed Kh. Zamil
|
||||
@ -53,8 +54,15 @@ namespace Esiur.Data
|
||||
foreach (var pt in resource.Instance.Template.Properties)
|
||||
{
|
||||
var rt = pt.Info.GetValue(resource, null);
|
||||
if (rt is DistributedPropertyContext)
|
||||
continue;
|
||||
|
||||
writer.WritePropertyName(options.PropertyNamingPolicy?.ConvertName(pt.Name) ?? pt.Name);
|
||||
JsonSerializer.Serialize(writer, rt, options);
|
||||
|
||||
if (rt is IResource)
|
||||
JsonSerializer.Serialize(writer, (IResource) rt, options);
|
||||
else
|
||||
JsonSerializer.Serialize(writer, rt, options);
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
|
@ -110,6 +110,10 @@ namespace Esiur.Data
|
||||
foreach (var p in pi)
|
||||
st[p.Name] = p.GetValue(obj);
|
||||
|
||||
var fi = type.GetTypeInfo().GetFields().Where(x => x.IsPublic);
|
||||
foreach (var f in fi)
|
||||
st[f.Name] = f.GetValue(obj);
|
||||
|
||||
return st;
|
||||
}
|
||||
//else
|
||||
|
@ -1,22 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Description>Distributed Resources Platform</Description>
|
||||
<Copyright>Ahmed Kh. Zamil</Copyright>
|
||||
<PackageLicenseUrl>https://github.com/Esiur/Esiur-dotnet/blob/master/LICENSE</PackageLicenseUrl>
|
||||
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Version>1.5.1</Version>
|
||||
<Version>1.6.1</Version>
|
||||
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
|
||||
<Authors>Ahmed Kh. Zamil</Authors>
|
||||
<AssemblyVersion>1.3.1.0</AssemblyVersion>
|
||||
<AssemblyVersion>1.6.0</AssemblyVersion>
|
||||
<Company>Esiur Foundation</Company>
|
||||
<FileVersion>1.3.1.0</FileVersion>
|
||||
<FileVersion>1.6.0</FileVersion>
|
||||
<AssemblyName>Esiur</AssemblyName>
|
||||
<RootNamespace>Esiur</RootNamespace>
|
||||
<PackageId>Esiur</PackageId>
|
||||
<Product>Esiur</Product>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
@ -55,6 +56,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.9.0" />
|
||||
<PackageReference Include="System.Diagnostics.StackTrace" Version="4.3.0" />
|
||||
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
|
||||
<PackageReference Include="System.Interactive.Async" Version="5.0.0" />
|
||||
@ -62,8 +64,12 @@
|
||||
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
|
||||
<PackageReference Include="System.Net.Security" Version="4.3.2" />
|
||||
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="5.0.1" />
|
||||
<PackageReference Include="System.Text.Json" Version="5.0.2" />
|
||||
<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.Analyzers" Version="3.3.2" PrivateAssets="all" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -69,7 +69,7 @@ namespace Esiur.Misc
|
||||
}catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
return "";
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,9 +433,9 @@ namespace Esiur.Misc
|
||||
|
||||
|
||||
|
||||
public static byte[] GenerateBytes(int Length)
|
||||
public static byte[] GenerateBytes(int length)
|
||||
{
|
||||
var b = new byte[Length];
|
||||
var b = new byte[length];
|
||||
rand.NextBytes(b);
|
||||
return b;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace Esiur.Net.DataLink
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ namespace Esiur.Net.DataLink
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
|
||||
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||
|
@ -69,7 +69,7 @@ namespace Esiur.Net.DataLink
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -76,7 +76,7 @@ namespace Esiur.Net.HTTP
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -112,7 +112,7 @@ namespace Esiur.Net.HTTP
|
||||
|
||||
private void IipConnection_OnReady(DistributedConnection sender)
|
||||
{
|
||||
Warehouse.Put(sender, sender.RemoteUsername, null, sender.Server);
|
||||
Warehouse.Put(sender.RemoteUsername, sender, null, sender.Server).Wait();
|
||||
}
|
||||
|
||||
public override AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||
|
@ -197,11 +197,20 @@ namespace Esiur.Net.IIP
|
||||
|
||||
if (socket.State == SocketState.Established &&
|
||||
session.LocalAuthentication.Type == AuthenticationType.Client)
|
||||
{
|
||||
Declare();
|
||||
}
|
||||
}
|
||||
|
||||
private void Declare()
|
||||
{
|
||||
var dmn = DC.ToBytes(session.LocalAuthentication.Domain);// domain);
|
||||
|
||||
if (session.LocalAuthentication.Method == AuthenticationMethod.Credentials)
|
||||
{
|
||||
// declare (Credentials -> No Auth, No Enctypt)
|
||||
|
||||
var un = DC.ToBytes(session.LocalAuthentication.Username);
|
||||
var dmn = DC.ToBytes(session.LocalAuthentication.Domain);// domain);
|
||||
|
||||
SendParams()
|
||||
.AddUInt8(0x60)
|
||||
@ -212,8 +221,27 @@ namespace Esiur.Net.IIP
|
||||
.AddUInt8Array(un)
|
||||
.Done();//, dmn, localNonce, (byte)un.Length, un);
|
||||
}
|
||||
}
|
||||
else if (session.LocalAuthentication.Method == AuthenticationMethod.Token)
|
||||
{
|
||||
|
||||
SendParams()
|
||||
.AddUInt8(0x70)
|
||||
.AddUInt8((byte)dmn.Length)
|
||||
.AddUInt8Array(dmn)
|
||||
.AddUInt8Array(localNonce)
|
||||
.AddUInt64(session.LocalAuthentication.TokenIndex)
|
||||
.Done();//, dmn, localNonce, token
|
||||
|
||||
}
|
||||
else if (session.LocalAuthentication.Method == AuthenticationMethod.None)
|
||||
{
|
||||
SendParams()
|
||||
.AddUInt8(0x40)
|
||||
.AddUInt8((byte)dmn.Length)
|
||||
.AddUInt8Array(dmn)
|
||||
.Done();//, dmn, localNonce, token
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new distributed connection.
|
||||
@ -451,12 +479,21 @@ namespace Esiur.Net.IIP
|
||||
IIPRequestInvokeFunctionNamedArguments(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
|
||||
break;
|
||||
|
||||
case IIPPacket.IIPPacketAction.GetProperty:
|
||||
IIPRequestGetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
|
||||
//case IIPPacket.IIPPacketAction.GetProperty:
|
||||
// IIPRequestGetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
|
||||
// break;
|
||||
//case IIPPacket.IIPPacketAction.GetPropertyIfModified:
|
||||
// IIPRequestGetPropertyIfModifiedSince(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.ResourceAge);
|
||||
// break;
|
||||
|
||||
case IIPPacket.IIPPacketAction.Listen:
|
||||
IIPRequestListen(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
|
||||
break;
|
||||
case IIPPacket.IIPPacketAction.GetPropertyIfModified:
|
||||
IIPRequestGetPropertyIfModifiedSince(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.ResourceAge);
|
||||
|
||||
case IIPPacket.IIPPacketAction.Unlisten:
|
||||
IIPRequestUnlisten(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
|
||||
break;
|
||||
|
||||
case IIPPacket.IIPPacketAction.SetProperty:
|
||||
IIPRequestSetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
|
||||
break;
|
||||
@ -531,14 +568,17 @@ namespace Esiur.Net.IIP
|
||||
IIPReplyInvoke(packet.CallbackId, packet.Content);
|
||||
break;
|
||||
|
||||
case IIPPacket.IIPPacketAction.GetProperty:
|
||||
IIPReply(packet.CallbackId, packet.Content);
|
||||
break;
|
||||
//case IIPPacket.IIPPacketAction.GetProperty:
|
||||
// IIPReply(packet.CallbackId, packet.Content);
|
||||
// break;
|
||||
|
||||
case IIPPacket.IIPPacketAction.GetPropertyIfModified:
|
||||
IIPReply(packet.CallbackId, packet.Content);
|
||||
break;
|
||||
case IIPPacket.IIPPacketAction.SetProperty:
|
||||
//case IIPPacket.IIPPacketAction.GetPropertyIfModified:
|
||||
// IIPReply(packet.CallbackId, packet.Content);
|
||||
// break;
|
||||
|
||||
case IIPPacketAction.Listen:
|
||||
case IIPPacketAction.Unlisten:
|
||||
case IIPPacketAction.SetProperty:
|
||||
IIPReply(packet.CallbackId);
|
||||
break;
|
||||
|
||||
@ -753,24 +793,34 @@ namespace Esiur.Net.IIP
|
||||
session.Id = new byte[32];
|
||||
r.NextBytes(session.Id);
|
||||
//SendParams((byte)0x28, session.Id);
|
||||
SendParams()
|
||||
.AddUInt8(0x28)
|
||||
.AddUInt8Array(session.Id)
|
||||
.Done();
|
||||
SendParams().AddUInt8(0x28)
|
||||
.AddUInt8Array(session.Id)
|
||||
.Done();
|
||||
|
||||
ready = true;
|
||||
Warehouse.Put(this, this.LocalUsername, null, Server).Then(x =>
|
||||
if (this.Instance == null)
|
||||
{
|
||||
Warehouse.Put(this.RemoteUsername, this, null, Server).Then(x =>
|
||||
{
|
||||
|
||||
ready = true;
|
||||
openReply?.Trigger(true);
|
||||
OnReady?.Invoke(this);
|
||||
|
||||
Server?.Membership.Login(session);
|
||||
loginDate = DateTime.Now;
|
||||
|
||||
}).Error(x =>
|
||||
{
|
||||
openReply?.TriggerError(x);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
ready = true;
|
||||
openReply?.Trigger(true);
|
||||
OnReady?.Invoke(this);
|
||||
|
||||
Server?.Membership.Login(session);
|
||||
|
||||
}).Error(x=>
|
||||
{
|
||||
openReply?.TriggerError(x);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//Global.Log("auth", LogType.Warning, "U:" + RemoteUsername + " IP:" + Socket.RemoteEndPoint.Address.ToString() + " S:AUTH");
|
||||
|
||||
@ -841,13 +891,21 @@ namespace Esiur.Net.IIP
|
||||
|
||||
ready = true;
|
||||
// put it in the warehouse
|
||||
Warehouse.Put(this, this.LocalUsername, null, Server).Then(x =>
|
||||
|
||||
if (this.Instance == null)
|
||||
{
|
||||
Warehouse.Put(this.LocalUsername, this, null, Server).Then(x =>
|
||||
{
|
||||
openReply?.Trigger(true);
|
||||
OnReady?.Invoke(this);
|
||||
|
||||
}).Error(x => openReply?.TriggerError(x));
|
||||
}
|
||||
else
|
||||
{
|
||||
openReply?.Trigger(true);
|
||||
OnReady?.Invoke(this);
|
||||
|
||||
}).Error(x=> openReply?.TriggerError(x));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (authPacket.Command == IIPAuthPacket.IIPAuthPacketCommand.Error)
|
||||
@ -957,28 +1015,7 @@ namespace Esiur.Net.IIP
|
||||
}
|
||||
|
||||
|
||||
protected void NetworkClose()
|
||||
{
|
||||
// clean up
|
||||
ready = false;
|
||||
readyToEstablish = false;
|
||||
|
||||
foreach (var x in requests.Values)
|
||||
x.TriggerError(new AsyncException(ErrorType.Management, 0, "Connection closed"));
|
||||
|
||||
foreach (var x in resourceRequests.Values)
|
||||
x.TriggerError(new AsyncException(ErrorType.Management, 0, "Connection closed"));
|
||||
|
||||
foreach (var x in templateRequests.Values)
|
||||
x.TriggerError(new AsyncException(ErrorType.Management, 0, "Connection closed"));
|
||||
|
||||
requests.Clear();
|
||||
resourceRequests.Clear();
|
||||
templateRequests.Clear();
|
||||
|
||||
foreach (var x in resources.Values)
|
||||
x.Suspend();
|
||||
}
|
||||
|
||||
public AsyncReply<bool> Connect(AuthenticationMethod method = AuthenticationMethod.Certificate, Sockets.ISocket socket = null, string hostname = null, ushort port = 0, string username = null, ulong tokenIndex = 0, byte[] passwordOrToken = null, string domain = null)
|
||||
{
|
||||
@ -1128,32 +1165,38 @@ namespace Esiur.Net.IIP
|
||||
protected override void Connected()
|
||||
{
|
||||
if (session.LocalAuthentication.Type == AuthenticationType.Client)
|
||||
{
|
||||
// declare (Credentials -> No Auth, No Enctypt)
|
||||
|
||||
var un = DC.ToBytes(session.LocalAuthentication.Username);
|
||||
var dmn = DC.ToBytes(session.LocalAuthentication.Domain);// domain);
|
||||
|
||||
SendParams()
|
||||
.AddUInt8(0x60)
|
||||
.AddUInt8((byte)dmn.Length)
|
||||
.AddUInt8Array(dmn)
|
||||
.AddUInt8Array(localNonce)
|
||||
.AddUInt8((byte)un.Length)
|
||||
.AddUInt8Array(un)
|
||||
.Done();
|
||||
}
|
||||
Declare();
|
||||
}
|
||||
|
||||
protected override void Disconencted()
|
||||
{
|
||||
// clean up
|
||||
readyToEstablish = false;
|
||||
|
||||
foreach (var x in requests.Values)
|
||||
x.TriggerError(new AsyncException(ErrorType.Management, 0, "Connection closed"));
|
||||
|
||||
foreach (var x in resourceRequests.Values)
|
||||
x.TriggerError(new AsyncException(ErrorType.Management, 0, "Connection closed"));
|
||||
|
||||
foreach (var x in templateRequests.Values)
|
||||
x.TriggerError(new AsyncException(ErrorType.Management, 0, "Connection closed"));
|
||||
|
||||
requests.Clear();
|
||||
resourceRequests.Clear();
|
||||
templateRequests.Clear();
|
||||
|
||||
foreach (var x in resources.Values)
|
||||
x.Suspend();
|
||||
|
||||
UnsubscribeAll();
|
||||
|
||||
Warehouse.Remove(this);
|
||||
|
||||
if (ready)
|
||||
{
|
||||
Server?.Membership.Logout(session);
|
||||
Warehouse.Remove(this);
|
||||
ready = false;
|
||||
UnsubscribeAll();
|
||||
}
|
||||
|
||||
ready = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -36,6 +36,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Esiur.Net.IIP
|
||||
{
|
||||
@ -54,7 +55,9 @@ namespace Esiur.Net.IIP
|
||||
|
||||
volatile uint callbackCounter = 0;
|
||||
|
||||
List<IResource> subscriptions = new List<IResource>();
|
||||
//List<IResource> subscriptions = new List<IResource>();
|
||||
Dictionary<IResource, List<byte>> subscriptions = new Dictionary<IResource, List<byte>>();// new List<IResource>();
|
||||
|
||||
object subscriptionsLock = new object();
|
||||
|
||||
AsyncQueue<DistributedResourceQueueItem> queue = new AsyncQueue<DistributedResourceQueueItem>();
|
||||
@ -108,13 +111,40 @@ namespace Esiur.Net.IIP
|
||||
|
||||
internal SendList SendEvent(IIPPacket.IIPPacketEvent evt)
|
||||
{
|
||||
//var bl = new BinaryList((byte)(evt));
|
||||
//bl.AddRange(args);
|
||||
//Send(bl.ToArray());
|
||||
|
||||
return (SendList)SendParams().AddUInt8((byte)(evt));
|
||||
}
|
||||
|
||||
internal AsyncReply SendListenRequest(uint instanceId, byte index)
|
||||
{
|
||||
var reply = new AsyncReply<object>();
|
||||
var c = callbackCounter++;
|
||||
requests.Add(c, reply);
|
||||
|
||||
SendParams().AddUInt8((byte)(0x40 | (byte)Packets.IIPPacket.IIPPacketAction.Listen))
|
||||
.AddUInt32(c)
|
||||
.AddUInt32(instanceId)
|
||||
.AddUInt8(index)
|
||||
.Done();
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
internal AsyncReply SendUnlistenRequest(uint instanceId, byte index)
|
||||
{
|
||||
var reply = new AsyncReply<object>();
|
||||
var c = callbackCounter++;
|
||||
requests.Add(c, reply);
|
||||
|
||||
SendParams().AddUInt8((byte)(0x40 | (byte)Packets.IIPPacket.IIPPacketAction.Unlisten))
|
||||
.AddUInt32(c)
|
||||
.AddUInt32(instanceId)
|
||||
.AddUInt8(index)
|
||||
.Done();
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
internal AsyncReply<object> SendInvokeByArrayArguments(uint instanceId, byte index, object[] parameters)
|
||||
{
|
||||
var pb = Codec.ComposeVarArray(parameters, this, true);
|
||||
@ -593,6 +623,7 @@ namespace Esiur.Net.IIP
|
||||
var r = res as IResource;
|
||||
// unsubscribe
|
||||
Unsubscribe(r);
|
||||
Subscribe(r);
|
||||
|
||||
//r.Instance.ResourceEventOccurred -= Instance_EventOccurred;
|
||||
//r.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred;
|
||||
@ -610,7 +641,6 @@ namespace Esiur.Net.IIP
|
||||
//r.Instance.ResourceModified += Instance_PropertyModified;
|
||||
//r.Instance.ResourceDestroyed += Instance_ResourceDestroyed;
|
||||
|
||||
Subscribe(r);
|
||||
//r.Instance.Children.OnAdd += Children_OnAdd;
|
||||
//r.Instance.Children.OnRemoved += Children_OnRemoved;
|
||||
|
||||
@ -770,7 +800,7 @@ namespace Esiur.Net.IIP
|
||||
// create the resource
|
||||
var resource = Activator.CreateInstance(type, args) as IResource;
|
||||
|
||||
Warehouse.Put(resource, name, store as IStore, parent).Then(ok =>
|
||||
Warehouse.Put( name, resource, store as IStore, parent).Then(ok =>
|
||||
{
|
||||
SendReply(IIPPacket.IIPPacketAction.CreateResource, callback)
|
||||
.AddUInt32(resource.Instance.Id)
|
||||
@ -1126,7 +1156,7 @@ namespace Esiur.Net.IIP
|
||||
if (Server?.EntryPoint != null)
|
||||
Server.EntryPoint.Query(resourceLink, this).Then(queryCallback);
|
||||
else
|
||||
Warehouse.Query(resourceLink).Then(x => queryCallback(x));
|
||||
Warehouse.Query(resourceLink).Then(queryCallback);
|
||||
}
|
||||
|
||||
void IIPRequestResourceAttribute(uint callback, uint resourceId)
|
||||
@ -1469,53 +1499,161 @@ namespace Esiur.Net.IIP
|
||||
});
|
||||
}
|
||||
|
||||
void IIPRequestGetProperty(uint callback, uint resourceId, byte index)
|
||||
void IIPRequestListen(uint callback, uint resourceId, byte index)
|
||||
{
|
||||
Warehouse.GetById(resourceId).Then((r) =>
|
||||
{
|
||||
if (r != null)
|
||||
{
|
||||
var pt = r.Instance.Template.GetFunctionTemplateByIndex(index);
|
||||
if (pt != null)
|
||||
var et = r.Instance.Template.GetEventTemplateByIndex(index);
|
||||
|
||||
if (et != null)
|
||||
{
|
||||
if (r is DistributedResource)
|
||||
{
|
||||
SendReply(IIPPacket.IIPPacketAction.GetProperty, callback)
|
||||
.AddUInt8Array(Codec.Compose((r as DistributedResource)._Get(pt.Index), this))
|
||||
.Done();
|
||||
(r as DistributedResource).Listen(et).Then(x =>
|
||||
{
|
||||
SendReply(IIPPacket.IIPPacketAction.Listen, callback).Done();
|
||||
}).Error(x => SendError(ErrorType.Exception, callback, (ushort)ExceptionCode.GeneralFailure));
|
||||
}
|
||||
else
|
||||
{
|
||||
#if NETSTANDARD
|
||||
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||
#else
|
||||
var pi = r.GetType().GetProperty(pt.Name);
|
||||
#endif
|
||||
lock(subscriptionsLock)
|
||||
{
|
||||
if (!subscriptions.ContainsKey(r))
|
||||
{
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.NotAttached);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pi != null)
|
||||
{
|
||||
SendReply(IIPPacket.IIPPacketAction.GetProperty, callback)
|
||||
.AddUInt8Array(Codec.Compose(pi.GetValue(r), this))
|
||||
.Done();
|
||||
}
|
||||
else
|
||||
{
|
||||
// pt found, pi not found, this should never happen
|
||||
if (subscriptions[r].Contains(index))
|
||||
{
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.AlreadyListened);
|
||||
return;
|
||||
}
|
||||
|
||||
subscriptions[r].Add(index);
|
||||
|
||||
SendReply(IIPPacket.IIPPacketAction.Listen, callback).Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pt not found
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.MethodNotFound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// resource not found
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void IIPRequestUnlisten(uint callback, uint resourceId, byte index)
|
||||
{
|
||||
Warehouse.GetById(resourceId).Then((r) =>
|
||||
{
|
||||
if (r != null)
|
||||
{
|
||||
var et = r.Instance.Template.GetEventTemplateByIndex(index);
|
||||
|
||||
if (et != null)
|
||||
{
|
||||
if (r is DistributedResource)
|
||||
{
|
||||
(r as DistributedResource).Unlisten(et).Then(x =>
|
||||
{
|
||||
SendReply(IIPPacket.IIPPacketAction.Unlisten, callback).Done();
|
||||
}).Error(x => SendError(ErrorType.Exception, callback, (ushort)ExceptionCode.GeneralFailure));
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (subscriptionsLock)
|
||||
{
|
||||
if (!subscriptions.ContainsKey(r))
|
||||
{
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.NotAttached);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!subscriptions[r].Contains(index))
|
||||
{
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.AlreadyUnlistened);
|
||||
return;
|
||||
}
|
||||
|
||||
subscriptions[r].Remove(index);
|
||||
|
||||
SendReply(IIPPacket.IIPPacketAction.Unlisten, callback).Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pt not found
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.MethodNotFound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// resource not found
|
||||
SendError(ErrorType.Management, callback, (ushort)ExceptionCode.ResourceNotFound);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// void IIPRequestGetProperty(uint callback, uint resourceId, byte index)
|
||||
// {
|
||||
// Warehouse.GetById(resourceId).Then((r) =>
|
||||
// {
|
||||
// if (r != null)
|
||||
// {
|
||||
// var pt = r.Instance.Template.GetPropertyTemplateByIndex(index);
|
||||
// if (pt != null)
|
||||
// {
|
||||
// if (r is DistributedResource)
|
||||
// {
|
||||
// SendReply(IIPPacket.IIPPacketAction.GetProperty, callback)
|
||||
// .AddUInt8Array(Codec.Compose((r as DistributedResource)._Get(pt.Index), this))
|
||||
// .Done();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
//#if NETSTANDARD
|
||||
// var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||
//#else
|
||||
// var pi = r.GetType().GetProperty(pt.Name);
|
||||
//#endif
|
||||
|
||||
// if (pi != null)
|
||||
// {
|
||||
// SendReply(IIPPacket.IIPPacketAction.GetProperty, callback)
|
||||
// .AddUInt8Array(Codec.Compose(pi.GetValue(r), this))
|
||||
// .Done();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // pt found, pi not found, this should never happen
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // pt not found
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // resource not found
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
void IIPRequestInquireResourceHistory(uint callback, uint resourceId, DateTime fromDate, DateTime toDate)
|
||||
{
|
||||
Warehouse.GetById(resourceId).Then((r) =>
|
||||
@ -1552,51 +1690,51 @@ namespace Esiur.Net.IIP
|
||||
});
|
||||
}
|
||||
|
||||
void IIPRequestGetPropertyIfModifiedSince(uint callback, uint resourceId, byte index, ulong age)
|
||||
{
|
||||
Warehouse.GetById(resourceId).Then((r) =>
|
||||
{
|
||||
if (r != null)
|
||||
{
|
||||
var pt = r.Instance.Template.GetFunctionTemplateByIndex(index);
|
||||
if (pt != null)
|
||||
{
|
||||
if (r.Instance.GetAge(index) > age)
|
||||
{
|
||||
#if NETSTANDARD
|
||||
var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||
#else
|
||||
var pi = r.GetType().GetProperty(pt.Name);
|
||||
#endif
|
||||
if (pi != null)
|
||||
{
|
||||
SendReply(IIPPacket.IIPPacketAction.GetPropertyIfModified, callback)
|
||||
.AddUInt8Array(Codec.Compose(pi.GetValue(r), this))
|
||||
.Done();
|
||||
}
|
||||
else
|
||||
{
|
||||
// pt found, pi not found, this should never happen
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SendReply(IIPPacket.IIPPacketAction.GetPropertyIfModified, callback)
|
||||
.AddUInt8((byte)DataType.NotModified)
|
||||
.Done();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pt not found
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// resource not found
|
||||
}
|
||||
});
|
||||
}
|
||||
// void IIPRequestGetPropertyIfModifiedSince(uint callback, uint resourceId, byte index, ulong age)
|
||||
// {
|
||||
// Warehouse.GetById(resourceId).Then((r) =>
|
||||
// {
|
||||
// if (r != null)
|
||||
// {
|
||||
// var pt = r.Instance.Template.GetFunctionTemplateByIndex(index);
|
||||
// if (pt != null)
|
||||
// {
|
||||
// if (r.Instance.GetAge(index) > age)
|
||||
// {
|
||||
//#if NETSTANDARD
|
||||
// var pi = r.GetType().GetTypeInfo().GetProperty(pt.Name);
|
||||
//#else
|
||||
// var pi = r.GetType().GetProperty(pt.Name);
|
||||
//#endif
|
||||
// if (pi != null)
|
||||
// {
|
||||
// SendReply(IIPPacket.IIPPacketAction.GetPropertyIfModified, callback)
|
||||
// .AddUInt8Array(Codec.Compose(pi.GetValue(r), this))
|
||||
// .Done();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // pt found, pi not found, this should never happen
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// SendReply(IIPPacket.IIPPacketAction.GetPropertyIfModified, callback)
|
||||
// .AddUInt8((byte)DataType.NotModified)
|
||||
// .Done();
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // pt not found
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // resource not found
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
void IIPRequestSetProperty(uint callback, uint resourceId, byte index, byte[] content)
|
||||
{
|
||||
@ -1973,7 +2111,7 @@ namespace Esiur.Net.IIP
|
||||
// ClassId, ResourceAge, ResourceLink, Content
|
||||
if (resource == null)
|
||||
{
|
||||
Warehouse.Put(dr, id.ToString(), this, null, tmp).Then((ok) =>
|
||||
Warehouse.Put(id.ToString(), dr, this, null, tmp).Then((ok) =>
|
||||
{
|
||||
Codec.ParsePropertyValueArray((byte[])rt[3], this).Then((ar) =>
|
||||
{
|
||||
@ -2242,7 +2380,7 @@ namespace Esiur.Net.IIP
|
||||
resource.Instance.ResourceModified += Instance_PropertyModified;
|
||||
resource.Instance.ResourceDestroyed += Instance_ResourceDestroyed;
|
||||
|
||||
subscriptions.Add(resource);
|
||||
subscriptions.Add(resource, new List<byte>());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2265,7 +2403,7 @@ namespace Esiur.Net.IIP
|
||||
{
|
||||
lock(subscriptionsLock)
|
||||
{
|
||||
foreach(var resource in subscriptions)
|
||||
foreach(var resource in subscriptions.Keys)
|
||||
{
|
||||
resource.Instance.ResourceEventOccurred -= Instance_EventOccurred;
|
||||
resource.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred;
|
||||
@ -2313,12 +2451,26 @@ namespace Esiur.Net.IIP
|
||||
if (et == null)
|
||||
return;
|
||||
|
||||
if (et.Listenable)
|
||||
{
|
||||
lock (subscriptionsLock)
|
||||
{
|
||||
// check the client requested listen
|
||||
if (!subscriptions.ContainsKey(resource))
|
||||
return;
|
||||
|
||||
if (!subscriptions[resource].Contains(et.Index))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!receivers(this.session))
|
||||
return;
|
||||
|
||||
if (resource.Instance.Applicable(this.session, ActionType.ReceiveEvent, et, issuer) == Ruling.Denied)
|
||||
return;
|
||||
|
||||
|
||||
// compose the packet
|
||||
SendEvent(IIPPacket.IIPPacketEvent.EventOccurred)
|
||||
.AddUInt32(resource.Instance.Id)
|
||||
@ -2334,6 +2486,18 @@ namespace Esiur.Net.IIP
|
||||
if (et == null)
|
||||
return;
|
||||
|
||||
if (et.Listenable)
|
||||
{
|
||||
lock (subscriptionsLock)
|
||||
{
|
||||
// check the client requested listen
|
||||
if (!subscriptions.ContainsKey(resource))
|
||||
return;
|
||||
|
||||
if (!subscriptions[resource].Contains(et.Index))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (resource.Instance.Applicable(this.session, ActionType.ReceiveEvent, et, null) == Ruling.Denied)
|
||||
return;
|
||||
|
@ -44,7 +44,7 @@ using Esiur.Resource.Template;
|
||||
|
||||
namespace Esiur.Net.IIP
|
||||
{
|
||||
|
||||
|
||||
//[System.Runtime.InteropServices.ComVisible(true)]
|
||||
public class DistributedResource : DynamicObject, IResource
|
||||
{
|
||||
@ -73,7 +73,7 @@ namespace Esiur.Net.IIP
|
||||
|
||||
DistributedResourceEvent[] events;
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Resource template for the remotely located resource.
|
||||
@ -105,7 +105,7 @@ namespace Esiur.Net.IIP
|
||||
/// </summary>
|
||||
public uint Id
|
||||
{
|
||||
get { return instanceId; }
|
||||
get { return instanceId; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -136,20 +136,20 @@ namespace Esiur.Net.IIP
|
||||
internal bool Attached => attached;
|
||||
|
||||
internal bool Suspended => suspended;
|
||||
|
||||
|
||||
// public DistributedResourceStack Stack
|
||||
|
||||
// public DistributedResourceStack Stack
|
||||
//{
|
||||
// get { return stack; }
|
||||
// get { return stack; }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new distributed resource.
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection responsible for the distributed resource.</param>
|
||||
/// <param name="template">Resource template.</param>
|
||||
/// <param name="instanceId">Instance Id given by the other end.</param>
|
||||
/// <param name="age">Resource age.</param>
|
||||
/// <summary>
|
||||
/// Create a new distributed resource.
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection responsible for the distributed resource.</param>
|
||||
/// <param name="template">Resource template.</param>
|
||||
/// <param name="instanceId">Instance Id given by the other end.</param>
|
||||
/// <param name="age">Resource age.</param>
|
||||
public DistributedResource(DistributedConnection connection, uint instanceId, ulong age, string link)
|
||||
{
|
||||
this.link = link;
|
||||
@ -207,7 +207,7 @@ namespace Esiur.Net.IIP
|
||||
attached = true;
|
||||
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void _EmitEventByIndex(byte index, object args)
|
||||
@ -232,6 +232,7 @@ namespace Esiur.Net.IIP
|
||||
return connection.SendInvokeByNamedArguments(instanceId, index, namedArgs);
|
||||
}
|
||||
|
||||
|
||||
public AsyncReply<object> _InvokeByArrayArguments(byte index, object[] args)
|
||||
{
|
||||
if (destroyed)
|
||||
@ -247,14 +248,52 @@ namespace Esiur.Net.IIP
|
||||
return connection.SendInvokeByArrayArguments(instanceId, index, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public AsyncReply Listen(EventTemplate et)
|
||||
{
|
||||
if (et == null)
|
||||
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.MethodNotFound, ""));
|
||||
|
||||
if (!et.Listenable)
|
||||
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotListenable, ""));
|
||||
|
||||
return connection.SendListenRequest(instanceId, et.Index);
|
||||
}
|
||||
|
||||
public AsyncReply Listen(string eventName)
|
||||
{
|
||||
var et = Instance.Template.GetEventTemplateByName(eventName);
|
||||
|
||||
return Listen(et);
|
||||
}
|
||||
|
||||
|
||||
public AsyncReply Unlisten(EventTemplate et)
|
||||
{
|
||||
if (et == null)
|
||||
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.MethodNotFound, ""));
|
||||
|
||||
if (!et.Listenable)
|
||||
return new AsyncReply().TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.NotListenable, ""));
|
||||
|
||||
return connection.SendUnlistenRequest(instanceId, et.Index);
|
||||
}
|
||||
|
||||
public AsyncReply Unlisten(string eventName)
|
||||
{
|
||||
var et = Instance.Template.GetEventTemplateByName(eventName);
|
||||
|
||||
return Unlisten(et);
|
||||
}
|
||||
|
||||
|
||||
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
|
||||
{
|
||||
var ft = Instance.Template.GetFunctionTemplateByName(binder.Name);
|
||||
|
||||
var reply = new AsyncReply<object>();
|
||||
|
||||
if (attached && ft!=null)
|
||||
if (attached && ft != null)
|
||||
{
|
||||
if (args.Length == 1)
|
||||
{
|
||||
@ -273,7 +312,7 @@ namespace Esiur.Net.IIP
|
||||
{
|
||||
result = _InvokeByArrayArguments(ft.Index, args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -380,7 +419,7 @@ namespace Esiur.Net.IIP
|
||||
return false;
|
||||
|
||||
var pt = Instance.Template.GetPropertyTemplateByName(binder.Name);
|
||||
|
||||
|
||||
if (pt != null)
|
||||
{
|
||||
_Set(pt.Index, value);
|
||||
@ -397,7 +436,7 @@ namespace Esiur.Net.IIP
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public async void InvokeMethod(byte index, object[] arguments, DistributedConnection sender)
|
||||
@ -426,10 +465,10 @@ namespace Esiur.Net.IIP
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Resource interface.
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Resource interface.
|
||||
/// </summary>
|
||||
public Instance Instance
|
||||
{
|
||||
get;
|
||||
|
@ -32,7 +32,7 @@ namespace Esiur.Net.IIP
|
||||
{
|
||||
public class DistributedSession : NetworkSession
|
||||
{
|
||||
Source Source { get; }
|
||||
Authentication Authentication;
|
||||
public Source Source { get; set; }
|
||||
public Authentication Authentication { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ using System.Text;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Data;
|
||||
using System.Net;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Esiur.Net.Packets
|
||||
{
|
||||
@ -241,12 +242,12 @@ namespace Esiur.Net.Packets
|
||||
// check limit
|
||||
if (postSize > data.Length - headerSize)
|
||||
return -(postSize - (data.Length - headerSize));
|
||||
|
||||
|
||||
|
||||
if (
|
||||
Headers["content-type"] == null
|
||||
|| Headers["content-type"] == ""
|
||||
|| Headers["content-type"].StartsWith("application/x-www-form-urlencoded"))
|
||||
|| Headers["content-type"].StartsWith("application/x-www-form-urlencoded"))
|
||||
{
|
||||
string[] PostVars = null;
|
||||
PostVars = Encoding.UTF8.GetString(data, (int)headerSize, (int)postSize).Split('&');
|
||||
@ -265,10 +266,10 @@ namespace Esiur.Net.Packets
|
||||
}
|
||||
else
|
||||
if (PostForms.Contains("unknown"))
|
||||
PostForms["unknown"] = PostForms["unknown"]
|
||||
+ "&" + WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J]));
|
||||
else
|
||||
PostForms.Add("unknown", WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J])));
|
||||
PostForms["unknown"] = PostForms["unknown"]
|
||||
+ "&" + WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J]));
|
||||
else
|
||||
PostForms.Add("unknown", WebUtility.HtmlDecode(WebUtility.UrlDecode(PostVars[J])));
|
||||
}
|
||||
}
|
||||
else if (Headers["content-type"].StartsWith("multipart/form-data"))
|
||||
@ -291,6 +292,10 @@ namespace Esiur.Net.Packets
|
||||
PostForms.Add(ps[0].Substring(st, ed - st), ps[1]);
|
||||
}
|
||||
}
|
||||
//else if (Headers["content-type"] == "application/json")
|
||||
//{
|
||||
// var json = DC.Clip(data, headerSize, postSize);
|
||||
//}
|
||||
else
|
||||
{
|
||||
//PostForms.Add(Headers["content-type"], Encoding.Default.GetString( ));
|
||||
|
@ -110,11 +110,11 @@ namespace Esiur.Net.Packets
|
||||
|
||||
// Request Invoke
|
||||
InvokeFunctionArrayArguments = 0x10,
|
||||
GetProperty,
|
||||
GetPropertyIfModified,
|
||||
SetProperty,
|
||||
InvokeFunctionNamedArguments,
|
||||
|
||||
Listen,
|
||||
Unlisten,
|
||||
SetProperty,
|
||||
|
||||
// Request Attribute
|
||||
GetAllAttributes = 0x18,
|
||||
UpdateAllAttributes,
|
||||
@ -543,7 +543,8 @@ namespace Esiur.Net.Packets
|
||||
offset += cl;
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.GetProperty)
|
||||
else if (Action == IIPPacketAction.Listen
|
||||
|| Action == IIPPacketAction.Unlisten)// .GetProperty)
|
||||
{
|
||||
if (NotEnough(offset, ends, 5))
|
||||
return -dataLengthNeeded;
|
||||
@ -554,20 +555,20 @@ namespace Esiur.Net.Packets
|
||||
MethodIndex = data[offset++];
|
||||
|
||||
}
|
||||
else if (Action == IIPPacketAction.GetPropertyIfModified)
|
||||
{
|
||||
if (NotEnough(offset, ends, 9))
|
||||
return -dataLengthNeeded;
|
||||
//else if (Action == IIPPacketAction.GetPropertyIfModified)
|
||||
//{
|
||||
// if (NotEnough(offset, ends, 9))
|
||||
// return -dataLengthNeeded;
|
||||
|
||||
ResourceId = data.GetUInt32(offset);
|
||||
offset += 4;
|
||||
// ResourceId = data.GetUInt32(offset);
|
||||
// offset += 4;
|
||||
|
||||
MethodIndex = data[offset++];
|
||||
// MethodIndex = data[offset++];
|
||||
|
||||
ResourceAge = data.GetUInt64(offset);
|
||||
offset += 8;
|
||||
// ResourceAge = data.GetUInt64(offset);
|
||||
// offset += 8;
|
||||
|
||||
}
|
||||
//}
|
||||
else if (Action == IIPPacketAction.SetProperty)
|
||||
{
|
||||
if (NotEnough(offset, ends, 6))
|
||||
@ -707,9 +708,9 @@ namespace Esiur.Net.Packets
|
||||
offset += cl;
|
||||
}
|
||||
else if (Action == IIPPacketAction.InvokeFunctionArrayArguments
|
||||
|| Action == IIPPacketAction.InvokeFunctionNamedArguments
|
||||
|| Action == IIPPacketAction.GetProperty
|
||||
|| Action == IIPPacketAction.GetPropertyIfModified)
|
||||
|| Action == IIPPacketAction.InvokeFunctionNamedArguments)
|
||||
//|| Action == IIPPacketAction.GetProperty
|
||||
//|| Action == IIPPacketAction.GetPropertyIfModified)
|
||||
{
|
||||
if (NotEnough(offset, ends, 1))
|
||||
return -dataLengthNeeded;
|
||||
@ -740,7 +741,9 @@ namespace Esiur.Net.Packets
|
||||
offset += (uint)size;
|
||||
}
|
||||
}
|
||||
else if (Action == IIPPacketAction.SetProperty)
|
||||
else if (Action == IIPPacketAction.SetProperty
|
||||
|| Action == IIPPacketAction.Listen
|
||||
|| Action == IIPPacketAction.Unlisten)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ namespace Esiur.Net.Packets
|
||||
}
|
||||
*/
|
||||
|
||||
PosixTime Timeval;
|
||||
//PosixTime Timeval;
|
||||
public byte[] Header;
|
||||
public byte[] Preamble;
|
||||
//public byte[] Payload;
|
||||
|
@ -165,7 +165,7 @@ namespace Esiur.Net.Sockets
|
||||
{
|
||||
ssl.BeginWrite(kv.Value, 0, kv.Value.Length, SendCallback, kv.Key);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch //(Exception ex)
|
||||
{
|
||||
asyncSending = false;
|
||||
try
|
||||
@ -179,7 +179,7 @@ namespace Esiur.Net.Sockets
|
||||
Close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex2)
|
||||
catch //(Exception ex2)
|
||||
{
|
||||
//state = SocketState.Closed;// .Terminated;
|
||||
Close();
|
||||
@ -439,7 +439,7 @@ namespace Esiur.Net.Sockets
|
||||
ssl.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveCallback, this);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch //(Exception ex)
|
||||
{
|
||||
if (state != SocketState.Closed && !sock.Connected)
|
||||
{
|
||||
|
@ -126,7 +126,7 @@ namespace Esiur.Net.Sockets
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch //(Exception ex)
|
||||
{
|
||||
if (socket.state != SocketState.Closed && !socket.sock.Connected)
|
||||
{
|
||||
@ -500,7 +500,7 @@ namespace Esiur.Net.Sockets
|
||||
socket.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex2)
|
||||
catch //(Exception ex2)
|
||||
{
|
||||
socket.Close();
|
||||
//socket.state = SocketState.Closed;// .Terminated;
|
||||
|
@ -118,6 +118,7 @@ namespace Esiur.Net.Sockets
|
||||
|
||||
public void Send(byte[] message)
|
||||
{
|
||||
|
||||
lock (sendLock)
|
||||
{
|
||||
if (held)
|
||||
@ -131,9 +132,8 @@ namespace Esiur.Net.Sockets
|
||||
|
||||
pkt_send.Message = message;
|
||||
|
||||
|
||||
if (pkt_send.Compose())
|
||||
sock.Send(pkt_send.Data);
|
||||
sock?.Send(pkt_send.Data);
|
||||
|
||||
}
|
||||
}
|
||||
@ -229,8 +229,6 @@ namespace Esiur.Net.Sockets
|
||||
if (pkt_send.Compose())
|
||||
sock.Send(pkt_send.Data);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace Esiur.Net.TCP
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ namespace Esiur.Net.UDP
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
20
Esiur/Proxy/GenerationInfo.cs
Normal file
20
Esiur/Proxy/GenerationInfo.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Proxy
|
||||
{
|
||||
public struct GenerationInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool ImplementInterface { get; set; }
|
||||
|
||||
public bool ImplementTrigger { get; set; }
|
||||
public IFieldSymbol[] Fields { get; set; }
|
||||
public ITypeSymbol ClassSymbol { get; set; }
|
||||
|
||||
public ClassDeclarationSyntax ClassDeclaration { get; set; }
|
||||
}
|
||||
}
|
71
Esiur/Proxy/ResourceGenerator.cs
Normal file
71
Esiur/Proxy/ResourceGenerator.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace Esiur.Proxy
|
||||
{
|
||||
[Generator]
|
||||
public class ResourceGenerator : ISourceGenerator
|
||||
{
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
{
|
||||
// Register receiver
|
||||
context.RegisterForSyntaxNotifications(() => new ResourceGeneratorReceiver());
|
||||
}
|
||||
|
||||
public void Execute(GeneratorExecutionContext context)
|
||||
{
|
||||
|
||||
if (!(context.SyntaxContextReceiver is ResourceGeneratorReceiver receiver))
|
||||
return;
|
||||
|
||||
//#if DEBUG
|
||||
// if (!Debugger.IsAttached)
|
||||
// {
|
||||
// Debugger.Launch();
|
||||
// }
|
||||
//#endif
|
||||
|
||||
//var toImplement = receiver.Classes.Where(x => x.Fields.Length > 0);
|
||||
|
||||
foreach (var ci in receiver.Classes)
|
||||
{
|
||||
var code = @$"using Esiur.Resource;
|
||||
using Esiur.Core;
|
||||
namespace { ci.ClassSymbol.ContainingNamespace.ToDisplayString() } {{
|
||||
";
|
||||
|
||||
if (ci.ImplementInterface)
|
||||
code += $"public partial class {ci.Name} {{";
|
||||
else
|
||||
{
|
||||
code += @$"public partial class {ci.Name} : IResource {{
|
||||
public Instance Instance {{ get; set; }}
|
||||
public event DestroyedEvent OnDestroy;
|
||||
public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
|
||||
";
|
||||
|
||||
if (!ci.ImplementTrigger)
|
||||
code += "public AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);";
|
||||
}
|
||||
|
||||
foreach (var f in ci.Fields)
|
||||
{
|
||||
var fn = f.Name;
|
||||
var pn = fn.Substring(0, 1).ToUpper() + fn.Substring(1);
|
||||
code += $@"[Public] public {f.Type} {pn} {{ get => {fn}; set {{ {fn} = value; Instance.Modified(); }} }}";
|
||||
}
|
||||
|
||||
code += "}}";
|
||||
|
||||
//System.IO.File.WriteAllText("C:\\www\\class.cs", code);
|
||||
context.AddSource(ci.Name + "_esiur.cs", code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
61
Esiur/Proxy/ResourceGeneratorReceiver.cs
Normal file
61
Esiur/Proxy/ResourceGeneratorReceiver.cs
Normal file
@ -0,0 +1,61 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Proxy
|
||||
{
|
||||
public class ResourceGeneratorReceiver : ISyntaxContextReceiver
|
||||
{
|
||||
|
||||
public List<GenerationInfo> Classes { get; } = new();
|
||||
|
||||
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
|
||||
{
|
||||
|
||||
if (context.Node is ClassDeclarationSyntax)
|
||||
{
|
||||
var cds = context.Node as ClassDeclarationSyntax;
|
||||
var cls = context.SemanticModel.GetDeclaredSymbol(cds) as ITypeSymbol;
|
||||
|
||||
if (cls.GetAttributes().Any(a => a.AttributeClass.ToDisplayString() == "Esiur.Resource.ResourceAttribute"))
|
||||
{
|
||||
//if (!Debugger.IsAttached)
|
||||
//{
|
||||
// Debugger.Launch();
|
||||
//}
|
||||
|
||||
var hasTrigger = cds.Members
|
||||
.Where(x => x is MethodDeclarationSyntax)
|
||||
.Select(x => context.SemanticModel.GetDeclaredSymbol(x) as IMethodSymbol)
|
||||
.Any(x => x.Name == "Trigger"
|
||||
&& x.Parameters.Length == 1
|
||||
&& x.Parameters[0].Type.ToDisplayString() == "Esiur.Resource.ResourceTrigger");
|
||||
|
||||
var fields = cds.Members.Where(x => x is FieldDeclarationSyntax)
|
||||
.Select(x => context.SemanticModel.GetDeclaredSymbol((x as FieldDeclarationSyntax).Declaration.Variables.First()) as IFieldSymbol)
|
||||
.Where(x => x.GetAttributes().Any(a => a.AttributeClass.ToDisplayString() == "Esiur.Resource.PublicAttribute"))
|
||||
.ToArray();
|
||||
|
||||
|
||||
// get fields
|
||||
Classes.Add(new GenerationInfo()
|
||||
{
|
||||
Name = cls.Name,
|
||||
ClassDeclaration = cds,
|
||||
ClassSymbol = cls,
|
||||
Fields = fields,
|
||||
ImplementInterface = cls.Interfaces.Any(x => x.ToDisplayString() == "Esiur.Resource.IResource"),
|
||||
ImplementTrigger = hasTrigger
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -11,7 +11,6 @@ namespace Esiur.Proxy
|
||||
public static class ResourceProxy
|
||||
{
|
||||
static Dictionary<Type, Type> cache = new Dictionary<Type, Type>();
|
||||
|
||||
|
||||
#if NETSTANDARD
|
||||
static MethodInfo modifyMethod = typeof(Instance).GetTypeInfo().GetMethod("Modified");
|
||||
@ -34,14 +33,14 @@ namespace Esiur.Proxy
|
||||
else
|
||||
return type;
|
||||
|
||||
if (type.FullName.Contains("Esiur.Proxy.T"))
|
||||
#if NETSTANDARD
|
||||
return type.GetTypeInfo().BaseType;
|
||||
#else
|
||||
return type.BaseType;
|
||||
#endif
|
||||
else
|
||||
return type;
|
||||
// if (type.FullName.Contains("Esiur.Proxy.T"))
|
||||
//#if NETSTANDARD
|
||||
// return type.GetTypeInfo().BaseType;
|
||||
//#else
|
||||
// return type.BaseType;
|
||||
//#endif
|
||||
// else
|
||||
// return type;
|
||||
}
|
||||
|
||||
public static Type GetProxy(Type type)
|
||||
@ -50,6 +49,13 @@ namespace Esiur.Proxy
|
||||
if (cache.ContainsKey(type))
|
||||
return cache[type];
|
||||
|
||||
// check if the type was made with code generation
|
||||
if (type.GetCustomAttribute<ResourceAttribute>(false) != null)
|
||||
{
|
||||
cache.Add(type, type);
|
||||
return type;
|
||||
}
|
||||
|
||||
#if NETSTANDARD
|
||||
var typeInfo = type.GetTypeInfo();
|
||||
|
||||
|
@ -41,7 +41,6 @@ namespace Esiur.Resource
|
||||
{
|
||||
|
||||
AsyncReply<bool> Trigger(ResourceTrigger trigger);
|
||||
|
||||
Instance Instance
|
||||
{
|
||||
get;
|
||||
|
42
Esiur/Resource/ListenableAttribute.cs
Normal file
42
Esiur/Resource/ListenableAttribute.cs
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 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.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Esiur.Resource
|
||||
{
|
||||
|
||||
[AttributeUsage(AttributeTargets.Event)]
|
||||
public class ListenableAttribute : System.Attribute
|
||||
{
|
||||
|
||||
public ListenableAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ using System.Text;
|
||||
|
||||
namespace Esiur.Resource
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Event | AttributeTargets.Class)]
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event | AttributeTargets.Class)]
|
||||
|
||||
public class PublicAttribute : Attribute
|
||||
{
|
||||
|
@ -47,6 +47,7 @@ namespace Esiur.Resource
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
|
||||
|
||||
protected virtual bool Create()
|
||||
{
|
||||
return true;
|
||||
|
15
Esiur/Resource/ResourceAttribute.cs
Normal file
15
Esiur/Resource/ResourceAttribute.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Resource
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
public class ResourceAttribute : Attribute
|
||||
{
|
||||
public ResourceAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,8 @@ namespace Esiur.Resource.Template
|
||||
set;
|
||||
}
|
||||
|
||||
public bool Listenable { get; set; }
|
||||
|
||||
public EventInfo Info { get; set; }
|
||||
|
||||
public override byte[] Compose()
|
||||
@ -24,9 +26,10 @@ namespace Esiur.Resource.Template
|
||||
|
||||
if (Expansion != null)
|
||||
{
|
||||
|
||||
var exp = DC.ToBytes(Expansion);
|
||||
return new BinaryList()
|
||||
.AddUInt8(0x50)
|
||||
.AddUInt8(Listenable ? (byte) 0x58 : (byte) 0x50)
|
||||
.AddUInt8((byte)name.Length)
|
||||
.AddUInt8Array(name)
|
||||
.AddInt32(exp.Length)
|
||||
@ -35,17 +38,18 @@ namespace Esiur.Resource.Template
|
||||
}
|
||||
else
|
||||
return new BinaryList()
|
||||
.AddUInt8(0x40)
|
||||
.AddUInt8(Listenable ? (byte) 0x48 : (byte) 0x40)
|
||||
.AddUInt8((byte)name.Length)
|
||||
.AddUInt8Array(name)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public EventTemplate(ResourceTemplate template, byte index, string name, string expansion = null)
|
||||
public EventTemplate(ResourceTemplate template, byte index, string name, string expansion = null, bool listenable=false)
|
||||
:base(template, MemberType.Property, index, name)
|
||||
{
|
||||
this.Expansion = expansion;
|
||||
this.Listenable = listenable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ namespace Esiur.Resource.Template
|
||||
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);
|
||||
var pt = new PropertyTemplate(this, i++, pi.Name);
|
||||
if (storageAttr != null)
|
||||
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
|
||||
|
||||
@ -184,7 +184,7 @@ namespace Esiur.Resource.Template
|
||||
pt.ReadExpansion = annotationAttr.Annotation;
|
||||
else
|
||||
pt.ReadExpansion = pi.PropertyType.Name;
|
||||
|
||||
|
||||
pt.Info = pi;
|
||||
//pt.Serilize = publicAttr.Serialize;
|
||||
properties.Add(pt);
|
||||
@ -209,6 +209,7 @@ namespace Esiur.Resource.Template
|
||||
if (privateAttr == null)
|
||||
{
|
||||
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
|
||||
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
|
||||
|
||||
var et = new EventTemplate(this, i++, ei.Name);
|
||||
et.Info = ei;
|
||||
@ -216,6 +217,9 @@ namespace Esiur.Resource.Template
|
||||
if (annotationAttr != null)
|
||||
et.Expansion = annotationAttr.Annotation;
|
||||
|
||||
if (listenableAttr != null)
|
||||
et.Listenable = true;
|
||||
|
||||
events.Add(et);
|
||||
}
|
||||
}
|
||||
@ -283,6 +287,7 @@ namespace Esiur.Resource.Template
|
||||
if (publicAttr != null)
|
||||
{
|
||||
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
|
||||
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
|
||||
|
||||
var et = new EventTemplate(this, i++, ei.Name);
|
||||
et.Info = ei;
|
||||
@ -290,6 +295,9 @@ namespace Esiur.Resource.Template
|
||||
if (annotationAttr != null)
|
||||
et.Expansion = annotationAttr.Annotation;
|
||||
|
||||
if (listenableAttr != null)
|
||||
et.Listenable = true;
|
||||
|
||||
events.Add(et);
|
||||
}
|
||||
}
|
||||
@ -340,6 +348,7 @@ namespace Esiur.Resource.Template
|
||||
b.AddUInt8Array(et.Compose());
|
||||
|
||||
content = b.ToArray();
|
||||
|
||||
}
|
||||
|
||||
public static ResourceTemplate Parse(byte[] data)
|
||||
@ -436,7 +445,8 @@ namespace Esiur.Resource.Template
|
||||
{
|
||||
|
||||
string expansion = null;
|
||||
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
|
||||
var hasExpansion = ((data[offset] & 0x10) == 0x10);
|
||||
var listenable = ((data[offset++] & 0x8) == 0x8);
|
||||
|
||||
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
|
||||
offset += (uint)data[offset] + 1;
|
||||
@ -449,7 +459,7 @@ namespace Esiur.Resource.Template
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var et = new EventTemplate(od, eventIndex++, name, expansion);
|
||||
var et = new EventTemplate(od, eventIndex++, name, expansion, listenable);
|
||||
|
||||
od.events.Add(et);
|
||||
|
||||
|
@ -57,11 +57,12 @@ namespace Esiur.Resource
|
||||
|
||||
static bool warehouseIsOpen = false;
|
||||
|
||||
public delegate void StoreConnectedEvent(IStore store, string name);
|
||||
public delegate void StoreDisconnectedEvent(IStore store);
|
||||
public delegate void StoreEvent(IStore store);//, string name);
|
||||
// public delegate void StoreDisconnectedEvent(IStore store);
|
||||
|
||||
public static event StoreConnectedEvent StoreConnected;
|
||||
public static event StoreDisconnectedEvent StoreDisconnected;
|
||||
public static event StoreEvent StoreConnected;
|
||||
//public static event StoreEvent StoreOpen;
|
||||
public static event StoreEvent StoreDisconnected;
|
||||
|
||||
public delegate AsyncReply<IStore> ProtocolInstance(string name, object properties);
|
||||
|
||||
@ -476,18 +477,43 @@ namespace Esiur.Resource
|
||||
|
||||
}
|
||||
|
||||
|
||||
//public static async AsyncReply<T> Push<T>(string path, T resource) where T : IResource
|
||||
//{
|
||||
// await Put(path, resource);
|
||||
// return resource;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Put a resource in the warehouse.
|
||||
/// </summary>
|
||||
/// <param name="resource">Resource instance.</param>
|
||||
/// <param name="name">Resource name.</param>
|
||||
/// <param name="resource">Resource instance.</param>
|
||||
/// <param name="store">IStore that manages the resource. Can be null if the resource is a store.</param>
|
||||
/// <param name="parent">Parent resource. if not presented the store becomes the parent for the resource.</param>
|
||||
public static async AsyncReply<bool> 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<T> Put<T>(string name, T resource, IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, ulong age = 0, IPermissionsManager manager = null, object attributes = null) where T:IResource
|
||||
{
|
||||
if (resource.Instance != null)
|
||||
throw new Exception("Resource has a store.");
|
||||
|
||||
var path = name.TrimStart('/').Split('/');
|
||||
|
||||
if (path.Length > 1)
|
||||
{
|
||||
if (parent != null)
|
||||
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)));
|
||||
|
||||
if (parent == null)
|
||||
throw new Exception("Can't find parent");
|
||||
|
||||
store = store ?? parent.Instance.Store;
|
||||
}
|
||||
|
||||
var instanceName = path.Last();
|
||||
|
||||
|
||||
var resourceReference = new WeakReference<IResource>(resource);
|
||||
|
||||
if (store == null)
|
||||
@ -523,7 +549,7 @@ namespace Esiur.Resource
|
||||
throw new Exception("Can't find a store for the resource.");
|
||||
}
|
||||
|
||||
resource.Instance = new Instance(resourceCounter++, name, resource, store, customTemplate, age);
|
||||
resource.Instance = new Instance(resourceCounter++, instanceName, resource, store, customTemplate, age);
|
||||
|
||||
if (attributes != null)
|
||||
resource.Instance.SetAttributes(Structure.FromObject(attributes));
|
||||
@ -535,44 +561,54 @@ namespace Esiur.Resource
|
||||
parent = null;
|
||||
|
||||
|
||||
|
||||
|
||||
if (resource is IStore)
|
||||
stores.TryAdd(resource as IStore, new List<WeakReference<IResource>>());
|
||||
|
||||
|
||||
if (!await store.Put(resource))
|
||||
return false;
|
||||
|
||||
|
||||
if (parent != null)
|
||||
try
|
||||
{
|
||||
await parent.Instance.Store.AddChild(parent, resource);
|
||||
await store.AddParent(resource, parent);
|
||||
}
|
||||
|
||||
var t = resource.GetType();
|
||||
Global.Counters["T-" + t.Namespace + "." + t.Name]++;
|
||||
|
||||
|
||||
resources.TryAdd(resource.Instance.Id, resourceReference);
|
||||
|
||||
if (warehouseIsOpen)
|
||||
{
|
||||
await resource.Trigger(ResourceTrigger.Initialize);
|
||||
if (resource is IStore)
|
||||
await resource.Trigger(ResourceTrigger.Open);
|
||||
}
|
||||
|
||||
if (resource is IStore)
|
||||
StoreConnected?.Invoke(resource as IStore, name);
|
||||
stores.TryAdd(resource as IStore, new List<WeakReference<IResource>>());
|
||||
|
||||
return true;
|
||||
|
||||
if (!await store.Put(resource))
|
||||
throw new Exception("Store failed to put the resource");
|
||||
//return default(T);
|
||||
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
await parent.Instance.Store.AddChild(parent, resource);
|
||||
await store.AddParent(resource, parent);
|
||||
}
|
||||
|
||||
var t = resource.GetType();
|
||||
Global.Counters["T-" + t.Namespace + "." + t.Name]++;
|
||||
|
||||
|
||||
resources.TryAdd(resource.Instance.Id, resourceReference);
|
||||
|
||||
if (warehouseIsOpen)
|
||||
{
|
||||
await resource.Trigger(ResourceTrigger.Initialize);
|
||||
if (resource is IStore)
|
||||
await resource.Trigger(ResourceTrigger.Open);
|
||||
}
|
||||
|
||||
if (resource is IStore)
|
||||
StoreConnected?.Invoke(resource as IStore);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Warehouse.Remove(resource);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return resource;
|
||||
|
||||
}
|
||||
|
||||
public static async AsyncReply<IResource> 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);
|
||||
|
||||
|
||||
@ -618,15 +654,33 @@ namespace Esiur.Resource
|
||||
{
|
||||
|
||||
var pi = type.GetProperty(p.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
|
||||
if (pi != null && pi.CanWrite)
|
||||
if (pi != null)
|
||||
{
|
||||
try
|
||||
if (pi.CanWrite)
|
||||
{
|
||||
pi.SetValue(res, p.Value);
|
||||
try
|
||||
{
|
||||
pi.SetValue(res, p.Value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Global.Log(ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
}
|
||||
else
|
||||
{
|
||||
var fi = type.GetField(p.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
|
||||
if (fi != null)
|
||||
{
|
||||
Global.Log(ex);
|
||||
try
|
||||
{
|
||||
fi.SetValue(res, p.Value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Global.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -634,8 +688,10 @@ namespace Esiur.Resource
|
||||
|
||||
if (store != null || parent != null || res is IStore)
|
||||
{
|
||||
if (!await Put(res, name, store, parent, null, 0, manager, attributes))
|
||||
return null;
|
||||
//if (!await Put(name, res, store, parent, null, 0, manager, attributes))
|
||||
// return null;
|
||||
|
||||
await Put(name, res, store, parent, null, 0, manager, attributes);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -35,11 +35,11 @@ using Esiur.Resource;
|
||||
|
||||
namespace Esiur.Security.Membership
|
||||
{
|
||||
public interface IMembership : IResource
|
||||
public interface IMembership
|
||||
{
|
||||
AsyncReply<bool> UserExists(string username, string domain);
|
||||
AsyncReply<byte[]> GetPassword(string username, string domain);
|
||||
AsyncReply<byte[]> GetToken(ulong TokenIndex, string domain);
|
||||
AsyncReply<byte[]> GetToken(ulong tokenIndex, string domain);
|
||||
AsyncReply<bool> Login(Session session);
|
||||
AsyncReply<bool> Logout(Session session);
|
||||
|
||||
|
@ -46,6 +46,7 @@ namespace Esiur.Security.Permissions
|
||||
|
||||
public bool Initialize(Structure settings, IResource resource)
|
||||
{
|
||||
this.settings = settings;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace Esiur.Stores
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
|
||||
OnDestroy?.Invoke(this);
|
||||
}
|
||||
|
||||
public string Link(IResource resource)
|
||||
@ -41,14 +41,14 @@ namespace Esiur.Stores
|
||||
return new AsyncReply<IResource>(null);
|
||||
}
|
||||
|
||||
public async AsyncReply<bool> Put(IResource resource)
|
||||
public AsyncReply<bool> Put(IResource resource)
|
||||
{
|
||||
|
||||
resources.Add(resource.Instance.Id, resource);// new WeakReference<IResource>(resource));
|
||||
resource.Instance.Variables["children"] = new AutoList<IResource, Instance>(resource.Instance);
|
||||
resource.Instance.Variables["parents"] = new AutoList<IResource, Instance>(resource.Instance);
|
||||
|
||||
return true;
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
|
||||
public AsyncReply<IResource> Retrieve(uint iid)
|
||||
|
@ -20,6 +20,7 @@ namespace Esiur.Stores
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
OnDestroy?.Invoke(this);
|
||||
|
||||
}
|
||||
|
||||
@ -31,19 +32,19 @@ namespace Esiur.Stores
|
||||
return null;
|
||||
}
|
||||
|
||||
public async AsyncReply<IResource> Get(string path)
|
||||
public AsyncReply<IResource> Get(string path)
|
||||
{
|
||||
foreach (var r in resources)
|
||||
if (r.Value.IsAlive && (r.Value.Target as IResource).Instance.Name == path)
|
||||
return r.Value.Target as IResource;
|
||||
return new AsyncReply<IResource>(r.Value.Target as IResource);
|
||||
|
||||
return null;
|
||||
return new AsyncReply<IResource>(null);
|
||||
}
|
||||
|
||||
public async AsyncReply<bool> Put(IResource resource)
|
||||
public AsyncReply<bool> Put(IResource resource)
|
||||
{
|
||||
resources.Add(resource.Instance.Id, new WeakReference( resource));// new WeakReference<IResource>(resource));
|
||||
return true;
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
|
||||
public AsyncReply<IResource> Retrieve(uint iid)
|
||||
|
Reference in New Issue
Block a user