diff --git a/IoTSharp.Data.InMemory/IoTSharp.Data.InMemory.csproj b/IoTSharp.Data.InMemory/IoTSharp.Data.InMemory.csproj index a5161f4dc80adba09821f97dc9181b87ea3fa933..1a8003b951e67b1250cfa6d5914c5b26f9452a3c 100644 --- a/IoTSharp.Data.InMemory/IoTSharp.Data.InMemory.csproj +++ b/IoTSharp.Data.InMemory/IoTSharp.Data.InMemory.csproj @@ -3,6 +3,12 @@ net6.0 + + + + + + @@ -17,8 +23,5 @@ - - - diff --git a/IoTSharp.Interpreter/CSharpScriptEngine.cs b/IoTSharp.Interpreter/CSharpScriptEngine.cs index 29ef8e8bc0c26b8b1da6a01fdae45a5a50885f5f..f2aeb3513f347eb02672dd8da86d6aaf429860f0 100644 --- a/IoTSharp.Interpreter/CSharpScriptEngine.cs +++ b/IoTSharp.Interpreter/CSharpScriptEngine.cs @@ -14,25 +14,52 @@ using IronPython.Runtime; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using System.Dynamic; +using Microsoft.Extensions.Caching.Memory; +using System.Text; + namespace IoTSharp.Interpreter { public class CSharpScriptEngine : ScriptEngineBase, IDisposable { private bool disposedValue; + private IMemoryCache _cache; - - public CSharpScriptEngine(ILogger logger, IOptions _opt):base(logger,_opt.Value, Task.Factory.CancellationToken) + public CSharpScriptEngine(ILogger logger, IOptions _opt, IMemoryCache cache) :base(logger,_opt.Value, Task.Factory.CancellationToken) { - //CSScript.EvaluatorConfig - + _cache = cache; } - public override string Do(string _source,string input) { - ICSAction csa = CSScript.Evaluator.LoadCode(_source); - dynamic result = csa.Run(input); + var runscript = _cache.GetOrCreate(_source, c => + { + var src = _source.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.TrimEntries); + StringBuilder _using = new StringBuilder(); + StringBuilder _body = new StringBuilder(); + src.ToList().ForEach(l => + { + if (l.StartsWith("using ")) + { + _using.AppendLine(l); + } + else + { + _body.AppendLine(l); + } + + }); + return CSScript.Evaluator + .CreateDelegate(@$" + {_using} + dynamic runscript(dynamic input) + {{ + {_body} + }}"); + }); + var expConverter = new ExpandoObjectConverter(); + dynamic obj = JsonConvert.DeserializeObject(input, expConverter); + dynamic result = runscript(obj); var json= System.Text.Json.JsonSerializer.Serialize(result); _logger.LogDebug($"source:{Environment.NewLine}{ _source}{Environment.NewLine}{Environment.NewLine}input:{Environment.NewLine}{ input}{Environment.NewLine}{Environment.NewLine} ouput:{Environment.NewLine}{ json}{Environment.NewLine}{Environment.NewLine}"); return json; @@ -64,19 +91,5 @@ namespace IoTSharp.Interpreter GC.SuppressFinalize(this); } } - - - public interface ICSAction - { - dynamic Run(string input); - - - - - - } - - - } diff --git a/IoTSharp.Interpreter/IoTSharp.Interpreter.csproj b/IoTSharp.Interpreter/IoTSharp.Interpreter.csproj index a98aa4c7dfb03afa3853c533e523012563186476..b907cceaae348a4d89ea34e564a5972bb9469707 100644 --- a/IoTSharp.Interpreter/IoTSharp.Interpreter.csproj +++ b/IoTSharp.Interpreter/IoTSharp.Interpreter.csproj @@ -12,6 +12,7 @@ + diff --git a/IoTSharp.Test/ScriptEngineTest.cs b/IoTSharp.Test/ScriptEngineTest.cs index dc7a53d10dd84cd98f60b1300f927586c560e9d0..efc4183db80b75f75c31e43281a40b4eda57c265 100644 --- a/IoTSharp.Test/ScriptEngineTest.cs +++ b/IoTSharp.Test/ScriptEngineTest.cs @@ -1,4 +1,5 @@ using IoTSharp.Interpreter; +using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -37,7 +38,7 @@ namespace IoTSharp.Test _lua_engine = new LuaScriptEngine (lgf.CreateLogger(), Options.Create(new Interpreter.EngineSetting() { Timeout = 4 })); _c_engine = new CScriptEngine(lgf.CreateLogger(), Options.Create(new Interpreter.EngineSetting() { Timeout = 4 })); _sql_engine=new SQLEngine(lgf.CreateLogger(), Options.Create(new Interpreter.EngineSetting() { Timeout = 4 })); - _csharp_engine = new CSharpScriptEngine (lgf.CreateLogger(), Options.Create(new Interpreter.EngineSetting() { Timeout = 4 })); + _csharp_engine = new CSharpScriptEngine (lgf.CreateLogger(), Options.Create(new Interpreter.EngineSetting() { Timeout = 4 }), new MemoryCache(new MemoryCacheOptions())); } [TestMethod] public void TestJavaScript() @@ -127,8 +128,9 @@ return fff:new() public void TestCSharpScript() { var intput = System.Text.Json.JsonSerializer.Serialize(new { temperature = 39, height = 192, weight = 121 }); - - string output = _csharp_engine.Do(@" + for (int i = 0; i < 1000; i++) + { + string output = _csharp_engine.Do(@" var _m = (input.height / 100); var output = new { fever= input.temperature > 38 ? true : false, @@ -136,10 +138,11 @@ var output = new { }; return output; ", intput); - - var t = new { fever = true, fat = true }; - var outpuobj = System.Text.Json.JsonSerializer.Deserialize(output, t.GetType()); - Assert.AreEqual(outpuobj, t); + var t = new { fever = true, fat = true }; + var outpuobj = System.Text.Json.JsonSerializer.Deserialize(output, t.GetType()); + Assert.AreEqual(outpuobj, t); + } + } } } diff --git a/IoTSharp/Extensions/ExecutorExtensions.cs b/IoTSharp/Extensions/ExecutorExtensions.cs deleted file mode 100644 index fbe2083a2082ba55f16515cc6c2471d99656fcfc..0000000000000000000000000000000000000000 --- a/IoTSharp/Extensions/ExecutorExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace IoTSharp.Extensions -{ - public static class ExecutorExtensions - { - - - - } -} diff --git a/IoTSharp/Extensions/LiteQueue.cs b/IoTSharp/Extensions/LiteQueue.cs deleted file mode 100644 index 9243a969d2b7f07c50d224e2707fc76b89398d2e..0000000000000000000000000000000000000000 --- a/IoTSharp/Extensions/LiteQueue.cs +++ /dev/null @@ -1,291 +0,0 @@ -/* Copyright 2018 by Nomadeon Software LLC. Licensed uinder MIT: https://opensource.org/licenses/MIT */ -using System; -using System.Collections.Generic; -using System.Text; -using LiteDB; -using System.Linq; -using System.Threading.Tasks; -#pragma warning disable CS1584,CS0419,CS1570 -namespace LiteQueue -{ - public class QueueEntry - { - public long Id { get; set; } - public T Payload { get; set; } - public bool IsCheckedOut { get; set; } - - public QueueEntry() - { - - } - - public QueueEntry(T payload) - { - Payload = payload; - } - } - /// - /// Uses LiteDB to provide a persisted, thread safe, (optionally) transactional, FIFO queue. - /// - /// Suitable for use on clients as a lightweight, portable alternative to MSMQ. Not recommended for use - /// on large server side applications due to performance limitations of LiteDB. - /// - public class LiteQueue - { - ILiteCollection> _collection; - bool _transactional = true; - readonly object _dequeueLock = new object(); - - /// - /// Impacts operation of method. Can only be set once in constructor. - /// - public bool IsTransactional - { - get - { - return _transactional; - } - } - - /// - /// Creates a collection for you in the database - /// - /// The LiteDB database. You are responsible for its lifecycle (using/dispose) - /// Name of the collection to create - /// Whether the queue should use transaction logic, default true - public LiteQueue(LiteDatabase db, string collectionName, bool transactional = true) - { - _collection = db.GetCollection>(collectionName); - _transactional = transactional; - } - - /// - /// Uses the provided database collection - /// - /// A LiteDB collection. - /// Whether the queue should use transaction logic, default true - public LiteQueue(ILiteCollection> collection, bool transactional = true) - { - _collection = collection; - _transactional = transactional; - _collection.EnsureIndex(x => x.Id); - _collection.EnsureIndex(x => x.IsCheckedOut); - } - /// - /// Creates a collection for you in the database, collection's name is - /// - /// The LiteDB database. You are responsible for its lifecycle (using/dispose) - /// Whether the queue should use transaction logic, default true - public LiteQueue(LiteDatabase db, bool transactional = true) - { - _collection = db.GetCollection>(typeof(T).Name); - _transactional = transactional; - } - - /// - /// Adds a single item to queue. See for adding a batch. - /// - /// - public void Enqueue(T item) - { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } - - QueueEntry insert = new QueueEntry(item); - - _collection.Insert(insert); - } - - /// - /// Adds a batch of items to the queue. See for adding a single item. - /// - /// - public void Enqueue(IEnumerable items) - { - List> inserts = new List>(); - foreach (var item in items) - { - inserts.Add(new QueueEntry(item)); - } - - _collection.InsertBulk(inserts); - } - - /// - /// Transactional queues: - /// Marks item as checked out but does not remove from queue. You are expected to later call or - /// Non-transactional queues: - /// Removes item from queue with no need to call or - /// - /// An item if found or null - public QueueEntry Dequeue() - { - var result = Dequeue(1); - if (result.Count == 0) - { - return null; - } - else - { - return result[0]; - } - } - - /// - /// Batch equivalent of - /// - /// The maximum number of items to dequeue - /// The items found or an empty collection (never null) - public List> Dequeue(int batchSize) - { - if (_transactional) - { - lock (_dequeueLock) - { - var items = _collection.Find(x => !x.IsCheckedOut, 0, batchSize); - - // Capture the result before changing IsCheckedOut, otherwise items is being changed - var result = new List>(items); - - foreach (var item in result) - { - item.IsCheckedOut = true; - _collection.Update(item); - } - - return result; - } - } - else - { - var items = _collection.Find(x => true, 0, batchSize); - var result = new List>(items); - - foreach (var item in items) - { - _collection.Delete(new BsonValue(item.Id)); - } - - return result; - } - } - - /// - /// Obtains list of items currently checked out (but not yet commited or aborted) as a result of Dequeue calls on a transactional queue - /// - /// Thrown when queue is not transactional - /// Items found or empty collection (never null) - public List> CurrentCheckouts() - { - if (!_transactional) - { - throw new InvalidOperationException("Cannot call " + nameof(CurrentCheckouts) + " unless queue is transactional"); - } - - var records = _collection.Find(item => item.IsCheckedOut); - return new List>(records); - } - - /// - /// Aborts all currently checked out items. Equivalent of calling followed by - /// - /// Thrown when queue is not transactional - public void ResetOrphans() - { - if (!_transactional) - { - throw new InvalidOperationException("Cannot call " + nameof(ResetOrphans) + " unless queue is transactional"); - } - - var checkouts = CurrentCheckouts(); - Abort(checkouts); - } - - /// - /// Aborts a transaction on a single item. See for batches. - /// - /// An item that was obtained from a call - /// Thrown when queue is not transactional - public void Abort(QueueEntry item) - { - if (!_transactional) - { - throw new InvalidOperationException("Cannot call " + nameof(Abort) + " unless queue is transactional"); - } - else if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } - - item.IsCheckedOut = false; - _collection.Update(item); - } - - /// - /// Aborts a transation on a group of items. See for a single item. - /// - /// Items that were obtained from a call - /// Thrown when queue is not transactional - public void Abort(IEnumerable> items) - { - foreach (var item in items) - { - Abort(item); - } - } - - /// - /// Commits a transaction on a single item. See for batches. - /// - /// An item that was obtained from a call - /// Thrown when queue is not transactional - public void Commit(QueueEntry item) - { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } - - if (!_transactional) - { - throw new InvalidOperationException("Cannot call " + nameof(Commit) + " unless queue is transactional"); - } - - BsonValue id = new BsonValue(item.Id); - _collection.Delete(id); - } - - - /// - /// Commits a transation on a group of items. See Items that were obtained from a call - /// Thrown when queue is not transactional - public void Commit(IEnumerable> items) - { - foreach (var item in items) - { - Commit(item); - } - } - - /// - /// Number of items in queue, including those that have been checked out. - /// - public int Count() - { - return _collection.Count(); - } - - /// - /// Removes all items from queue, including any that have been checked out. - /// - public void Clear() - { - _collection.DeleteAll(); - } - } -} -#pragma warning restore CS1584, CS0419, CS1570 \ No newline at end of file diff --git a/IoTSharp/IoTSharp.xml b/IoTSharp/IoTSharp.xml index f518ff007488383c69ed7d0bd1b174d957a1b73e..af8b6f39c66b5254e901d77f28c50deb0d7f7644 100644 --- a/IoTSharp/IoTSharp.xml +++ b/IoTSharp/IoTSharp.xml @@ -922,113 +922,5 @@ 解决单例注入问题 jy - - - Uses LiteDB to provide a persisted, thread safe, (optionally) transactional, FIFO queue. - - Suitable for use on clients as a lightweight, portable alternative to MSMQ. Not recommended for use - on large server side applications due to performance limitations of LiteDB. - - - - - Impacts operation of method. Can only be set once in constructor. - - - - - Creates a collection for you in the database - - The LiteDB database. You are responsible for its lifecycle (using/dispose) - Name of the collection to create - Whether the queue should use transaction logic, default true - - - - Uses the provided database collection - - A LiteDB collection. - Whether the queue should use transaction logic, default true - - - - Creates a collection for you in the database, collection's name is - - The LiteDB database. You are responsible for its lifecycle (using/dispose) - Whether the queue should use transaction logic, default true - - - - Adds a single item to queue. See for adding a batch. - - - - - - Adds a batch of items to the queue. See for adding a single item. - - - - - - Transactional queues: - Marks item as checked out but does not remove from queue. You are expected to later call or - Non-transactional queues: - Removes item from queue with no need to call or - - An item if found or null - - - - Batch equivalent of - - The maximum number of items to dequeue - The items found or an empty collection (never null) - - - - Obtains list of items currently checked out (but not yet commited or aborted) as a result of Dequeue calls on a transactional queue - - Thrown when queue is not transactional - Items found or empty collection (never null) - - - - Aborts all currently checked out items. Equivalent of calling followed by - - Thrown when queue is not transactional - - - - Aborts a transaction on a single item. See for batches. - - An item that was obtained from a call - Thrown when queue is not transactional - - - - Aborts a transation on a group of items. See for a single item. - - Items that were obtained from a call - Thrown when queue is not transactional - - - - Commits a transaction on a single item. See for batches. - - An item that was obtained from a call - Thrown when queue is not transactional - - - - - Number of items in queue, including those that have been checked out. - - - - - Removes all items from queue, including any that have been checked out. - -