瀏覽代碼

PosterEngine ground work (DON'T MERGE to PRDUCTION YET)

Kenric Nugteren 1 年之前
父節點
當前提交
17e7219254

+ 0 - 4
InABox.Configuration/FodyWeavers.xml

@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
-    <PropertyChanged/>
-</Weavers>

+ 0 - 74
InABox.Configuration/FodyWeavers.xsd

@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
-  <!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
-  <xs:element name="Weavers">
-    <xs:complexType>
-      <xs:all>
-        <xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
-          <xs:complexType>
-            <xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
-              <xs:annotation>
-                <xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-            <xs:attribute name="TriggerDependentProperties" type="xs:boolean">
-              <xs:annotation>
-                <xs:documentation>Used to control if the Dependent properties feature is enabled.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-            <xs:attribute name="EnableIsChangedProperty" type="xs:boolean">
-              <xs:annotation>
-                <xs:documentation>Used to control if the IsChanged property feature is enabled.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-            <xs:attribute name="EventInvokerNames" type="xs:string">
-              <xs:annotation>
-                <xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-            <xs:attribute name="CheckForEquality" type="xs:boolean">
-              <xs:annotation>
-                <xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-            <xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
-              <xs:annotation>
-                <xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-            <xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
-              <xs:annotation>
-                <xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-            <xs:attribute name="SuppressWarnings" type="xs:boolean">
-              <xs:annotation>
-                <xs:documentation>Used to turn off build warnings from this weaver.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-            <xs:attribute name="SuppressOnPropertyNameChangedWarning" type="xs:boolean">
-              <xs:annotation>
-                <xs:documentation>Used to turn off build warnings about mismatched On_PropertyName_Changed methods.</xs:documentation>
-              </xs:annotation>
-            </xs:attribute>
-          </xs:complexType>
-        </xs:element>
-      </xs:all>
-      <xs:attribute name="VerifyAssembly" type="xs:boolean">
-        <xs:annotation>
-          <xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
-        </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="VerifyIgnoreCodes" type="xs:string">
-        <xs:annotation>
-          <xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
-        </xs:annotation>
-      </xs:attribute>
-      <xs:attribute name="GenerateXsd" type="xs:boolean">
-        <xs:annotation>
-          <xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
-        </xs:annotation>
-      </xs:attribute>
-    </xs:complexType>
-  </xs:element>
-</xs:schema>

+ 0 - 27
InABox.Configuration/InABox.Configuration.csproj

@@ -1,27 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <ReleaseVersion>1.00</ReleaseVersion>
-        <SynchReleaseVersion>false</SynchReleaseVersion>
-        <TargetFramework>netstandard2.1</TargetFramework>
-		<Nullable>Enable</Nullable>
-    </PropertyGroup>
-
-    <ItemGroup>
-        <PackageReference Include="Fody" Version="6.6.3">
-            <PrivateAssets>all</PrivateAssets>
-            <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
-        </PackageReference>
-        <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
-        <PackageReference Include="PropertyChanged.Fody" Version="3.4.1" />
-    </ItemGroup>
-
-    <ItemGroup>
-        <ProjectReference Include="..\InABox.Core\InABox.Core.csproj" />
-    </ItemGroup>
-
-    <ItemGroup>
-        <None Remove=".gitignore" />
-    </ItemGroup>
-
-</Project>

+ 0 - 57
InABox.Configuration/README.md

@@ -1,57 +0,0 @@
-**Edit a file, create a new file, and clone from Bitbucket in under 2 minutes**
-
-When you're done, you can delete the content in this README and update the file with details for others getting started
-with your repository.
-
-*We recommend that you open this README in another tab as you perform the tasks below. You
-can [watch our video](https://youtu.be/0ocf7u76WSo) for a full demo of all the steps in this tutorial. Open the video in
-a new tab to avoid leaving Bitbucket.*
-
----
-
-## Edit a file
-
-You’ll start by editing this README file to learn how to edit a file in Bitbucket.
-
-1. Click **Source** on the left side.
-2. Click the README.md link from the list of files.
-3. Click the **Edit** button.
-4. Delete the following text: *Delete this line to make a change to the README from Bitbucket.*
-5. After making your change, click **Commit** and then **Commit** again in the dialog. The commit page will open and
-   you’ll see the change you just made.
-6. Go back to the **Source** page.
-
----
-
-## Create a file
-
-Next, you’ll add a new file to this repository.
-
-1. Click the **New file** button at the top of the **Source** page.
-2. Give the file a filename of **contributors.txt**.
-3. Enter your name in the empty file space.
-4. Click **Commit** and then **Commit** again in the dialog.
-5. Go back to the **Source** page.
-
-Before you move on, go ahead and explore the repository. You've already seen the **Source** page, but check out the **
-Commits**, **Branches**, and **Settings** pages.
-
----
-
-## Clone a repository
-
-Use these steps to clone from SourceTree, our client for using the repository command-line free. Cloning allows you to
-work on your files locally. If you don't yet have
-SourceTree, [download and install first](https://www.sourcetreeapp.com/). If you prefer to clone from the command line,
-see [Clone a repository](https://confluence.atlassian.com/x/4whODQ).
-
-1. You’ll see the clone button under the **Source** heading. Click that button.
-2. Now click **Check out in SourceTree**. You may need to create a SourceTree account or log in.
-3. When you see the **Clone New** dialog in SourceTree, update the destination path and name if you’d like to and then
-   click **Clone**.
-4. Open the directory you just created to see your repository’s files.
-
-Now that you're more familiar with your Bitbucket repository, go ahead and add a new file locally. You
-can [push your change back to Bitbucket with SourceTree](https://confluence.atlassian.com/x/iqyBMg), or you
-can [add, commit,](https://confluence.atlassian.com/x/8QhODQ)
-and [push from the command line](https://confluence.atlassian.com/x/NQ0zDQ).

+ 0 - 0
InABox.Configuration/ConfigurationCache.cs → InABox.Core/Configuration/ConfigurationCache.cs


+ 0 - 0
InABox.Configuration/ConfigurationUtils.cs → InABox.Core/Configuration/ConfigurationUtils.cs


+ 0 - 0
InABox.Configuration/GlobalConfiguration.cs → InABox.Core/Configuration/GlobalConfiguration.cs


+ 0 - 0
InABox.Configuration/IConfiguration.cs → InABox.Core/Configuration/IConfiguration.cs


+ 0 - 0
InABox.Configuration/LocalConfiguration.cs → InABox.Core/Configuration/LocalConfiguration.cs


+ 0 - 0
InABox.Configuration/UserConfiguration.cs → InABox.Core/Configuration/UserConfiguration.cs


+ 12 - 16
InABox.Core/Export.cs

@@ -157,27 +157,23 @@ namespace InABox.Core
 
         public override void Export(Stream stream, CoreTable table)
         {
-            using (var sw = new StreamWriter(stream, Encoding.Unicode))
+            using var sw = new StreamWriter(stream, Encoding.Unicode);
+            var row = new List<string>();
+            foreach (var column in table.Columns)
+                row.Add(column.ColumnName);
+
+            sw.WriteLine(string.Join(Convert.ToString(Delimiter), row));
+            foreach (var datarow in table.Rows)
             {
-                var row = new List<string>();
+                row.Clear();
                 foreach (var column in table.Columns)
-                    row.Add(column.ColumnName);
-
-                sw.WriteLine(string.Join(Convert.ToString(Delimiter), row));
-                foreach (var datarow in table.Rows)
                 {
-                    row.Clear();
-                    foreach (var column in table.Columns)
-                    {
-                        var o = datarow[column.ColumnName];
-                        row.Add(o != null ? o.ToString() : "");
-                    }
-
-                    sw.WriteLine(string.Join(Convert.ToString(Delimiter), row));
+                    var o = datarow[column.ColumnName];
+                    row.Add(o != null ? o.ToString() : "");
                 }
-            }
 
-            ;
+                sw.WriteLine(string.Join(Convert.ToString(Delimiter), row));
+            }
         }
     }
 

+ 18 - 0
InABox.Core/Postable/IPostable.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace InABox.Core
+{
+    /// <summary>
+    /// Flags an <see cref="Entity"/> as "Postable"; that is, it can be processed by an <see cref="IPoster{TEntity,TSettings}"/>.
+    /// </summary>
+    public interface IPostable
+    {
+        /// <summary>
+        /// At what time this <see cref="IPostable"/> was processed. Set to <see cref="DateTime.MinValue"/> if not processed yet.
+        /// When the <see cref="IPostable"/> is processed, this should be updated, so that we don't process things twice.
+        /// </summary>
+        DateTime Posted { get; set; }
+    }
+}

+ 20 - 0
InABox.Core/Postable/IPoster.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace InABox.Core
+{
+    /// <summary>
+    /// Base interface for all "Posters" - classes that define the means of processing an <see cref="IPostable"/> <see cref="Entity"/>.
+    /// There is little point in directly implementing this; rather, one should implement a subinterface.
+    /// The functionality of any <see cref="IPoster{TEntity,TSettings}"/> is essentially the default functionality, and, based on the subinterface implemented,
+    /// will be scriptable.
+    /// </summary>
+    /// <typeparam name="TEntity">The type of entity that this poster can process.</typeparam>
+    /// <typeparam name="TSettings">The <see cref="PosterSettings{TEntity}"/> specific to this type of poster.</typeparam>
+    public interface IPoster<TEntity, TSettings>
+        where TEntity : Entity, IPostable
+        where TSettings : PosterSettings<TEntity>
+    {
+    }
+}

+ 21 - 0
InABox.Core/Postable/PostableSettings.cs

@@ -0,0 +1,21 @@
+using InABox.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace InABox.Core
+{
+    /// <summary>
+    /// The global settings for an <see cref="IPostable"/> of a certain <typeparamref name="TEntity"/>.
+    /// </summary>
+    /// <typeparam name="TEntity"></typeparam>
+    public class PostableSettings<TEntity> : IGlobalConfigurationSettings
+        where TEntity : Entity, IPostable
+    {
+        /// <summary>
+        /// What kind of <see cref="IPoster{TEntity, TSettings}"/> is to be used, globally; this will be a type name.
+        /// </summary>
+        [ComboLookupEditor(typeof(PosterTypeLookup))]
+        public string PosterType { get; set; }
+    }
+}

+ 51 - 0
InABox.Core/Postable/PosterEngine.cs

@@ -0,0 +1,51 @@
+using InABox.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace InABox.Core
+{
+    public interface IPosterEngine<TPostable>
+        where TPostable : Entity, IPostable
+    {
+        bool Process(IEnumerable<TPostable> posts);
+    }
+
+    public abstract class PosterEngine<TPostable, TPoster, TSettings> : IPosterEngine<TPostable>
+        where TPostable : Entity, IPostable
+        where TPoster : IPoster<TPostable, TSettings>
+        where TSettings : PosterSettings<TPostable>, new()
+    {
+        protected static TPoster Poster = GetPoster();
+
+        private static Type[]? _posters;
+
+        private static TPoster GetPoster()
+        {
+            _posters ??= CoreUtils.TypeList(
+                AppDomain.CurrentDomain.GetAssemblies(),
+                x => x.IsClass
+                    && !x.IsAbstract
+                    && !x.IsGenericType
+                    && x.HasInterface(typeof(IPoster<,>))
+            ).ToArray();
+
+            var type = _posters.Where(x => typeof(TPoster).IsAssignableFrom(x)).FirstOrDefault()
+                ?? throw new Exception($"No poster of type {typeof(TPoster)}.");
+            return (TPoster)Activator.CreateInstance(type);
+        }
+
+        protected static TSettings GetSettings()
+        {
+            return new GlobalConfiguration<TSettings>(typeof(TPostable).Name).Load();
+        }
+
+        protected static string? GetScript()
+        {
+            return GetSettings().Script;
+        }
+
+        public abstract bool Process(IEnumerable<TPostable> posts);
+    }
+}

+ 18 - 0
InABox.Core/Postable/PosterSettings.cs

@@ -0,0 +1,18 @@
+using InABox.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace InABox.Core
+{
+    /// <summary>
+    /// The settings for a given <see cref="IPoster{TEntity, TSettings}"/>.
+    /// </summary>
+    /// <typeparam name="TEntity"></typeparam>
+    public class PosterSettings<TEntity> : IGlobalConfigurationSettings
+        where TEntity : Entity, IPostable
+    {
+        [ScriptEditor]
+        public string? Script { get; set; }
+    }
+}

+ 19 - 0
InABox.Core/Postable/PosterTypeLookup.cs

@@ -0,0 +1,19 @@
+using InABox.Clients;
+using System.Linq;
+
+namespace InABox.Core
+{
+    internal class PosterTypeLookup : LookupGenerator<object>
+    {
+        public PosterTypeLookup(object[]? items) : base(items)
+        {
+            var classes = CoreUtils.Entities.Where(
+                x => x.IsSubclassOf(typeof(Entity))
+                && x.HasInterface(typeof(IPoster<,>)))
+                .OrderBy(x => x.EntityName().Split('.').Last()).ToArray();
+            foreach (var entity in classes)
+                if (ClientFactory.IsSupported(entity))
+                    AddValue(entity.EntityName(), entity.EntityName().Split('.').Last());
+        }
+    }
+}

+ 44 - 0
InABox.Core/Postable/PosterUtils.cs

@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace InABox.Core
+{
+    public static class PosterUtils
+    {
+        private static Dictionary<Type, Type>? _posterEngines;
+
+        private static Dictionary<Type, Type> GetPosterEngines()
+        {
+            _posterEngines ??= CoreUtils.TypeList(
+                AppDomain.CurrentDomain.GetAssemblies(),
+                x => x.IsClass
+                    && !x.IsAbstract
+                    && x.GenericTypeArguments.Length == 1
+                    && x.HasInterface(typeof(IPosterEngine<>))
+            ).ToDictionary(
+                x => x.GetInterfaceDefinition(typeof(IPosterEngine<>))!.GenericTypeArguments[0],
+                x => x);
+            return _posterEngines;
+        }
+
+        public static Type GetEngine<T>()
+            where T : Entity, IPostable
+        {
+            return GetPosterEngines().GetValueOrDefault(typeof(T))
+                ?? throw new Exception($"No poster engine for type {typeof(T).Name}");
+        }
+        public static IPosterEngine<T> CreateEngine<T>()
+            where T : Entity, IPostable
+        {
+            return (Activator.CreateInstance(GetEngine<T>()) as IPosterEngine<T>)!;
+        }
+
+        public static bool Process<T>(IEnumerable<T> entities)
+            where T : Entity, IPostable
+        {
+            return CreateEngine<T>().Process(entities);
+        }
+    }
+}

+ 0 - 1
InABox.Database/InABox.Database.csproj

@@ -14,7 +14,6 @@
     </ItemGroup>
 
     <ItemGroup>
-        <ProjectReference Include="..\InABox.Configuration\InABox.Configuration.csproj" />
         <ProjectReference Include="..\InABox.Core\InABox.Core.csproj" />
         <ProjectReference Include="..\inabox.logging.shared\InABox.Logging.Shared.csproj" />
         <ProjectReference Include="..\InABox.Scripting\InABox.Scripting.csproj" />

+ 60 - 0
InABox.Poster.CSV/CSVPosterEngine.cs

@@ -0,0 +1,60 @@
+using CsvHelper;
+using InABox.Core;
+using InABox.Scripting;
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace InABox.Poster.CSV
+{
+    public class CSVPosterEngine<TPostable> : PosterEngine<TPostable, ICSVPoster<TPostable>, CSVPosterSettings<TPostable>>
+        where TPostable : Entity, IPostable
+    {
+        public override bool Process(IEnumerable<TPostable> posts)
+        {
+            var settings = GetSettings();
+
+            ICSVExport results;
+            if(!string.IsNullOrWhiteSpace(settings.Script))
+            {
+                var document = new ScriptDocument(settings.Script);
+                document.Properties.Add(new ScriptProperty("Results", null));
+                document.Compile();
+                document.Execute(methodname: "Process");
+
+                var resultsObject = document.GetValue("Results");
+                results = (resultsObject as ICSVExport)
+                    ?? throw new Exception($"Script Results property expected to be ICSVExport, got {resultsObject}");
+            }
+            else
+            {
+                results = Poster.Process(posts);
+            }
+
+            var dlg = new SaveFileDialog()
+            {
+                FileName = settings.DefaultOutputFile,
+                Filter = "CSV Files (*.csv)|*.csv"
+            };
+
+            if(dlg.ShowDialog() == true)
+            {
+                using var writer = new StreamWriter(dlg.FileName);
+                using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
+                csv.Context.RegisterClassMap(results.ClassMap.ClassMap);
+
+                var method = typeof(CsvWriter).GetMethods()
+                    .Where(x => x.Name == nameof(CsvWriter.WriteRecords) && x.GetGenericArguments().Length == 1).First()
+                    .MakeGenericMethod(results.Type);
+                method.Invoke(csv, new object?[] { results.Records });
+                return true;
+            }
+            return false;
+        }
+    }
+}

+ 16 - 0
InABox.Poster.CSV/CSVPosterSettings.cs

@@ -0,0 +1,16 @@
+using InABox.Core;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace InABox.Poster.CSV
+{
+    public class CSVPosterSettings<TEntity> : PosterSettings<TEntity>
+        where TEntity : Entity, IPostable
+    {
+        [FileNameEditor("CSV Files (*.csv)|*.csv", RequireExisting = false)]
+        public string DefaultOutputFile { get; set; }
+    }
+}

+ 95 - 0
InABox.Poster.CSV/ICSVPoster.cs

@@ -0,0 +1,95 @@
+using CsvHelper.Configuration;
+using InABox.Core;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Text;
+
+namespace InABox.Poster.CSV
+{
+    public interface ICSVClassMap
+    {
+        ClassMap ClassMap { get; }
+    }
+
+    public interface ICSVClassMap<T> : ICSVClassMap
+    {
+        new ClassMap<T> ClassMap { get; }
+
+        ClassMap ICSVClassMap.ClassMap => ClassMap;
+
+        void Map(string name, Expression<Func<T, object>> expr);
+    }
+
+    public class CSVClassMap<T> : ClassMap<T>, ICSVClassMap<T>
+    {
+        public ClassMap<T> ClassMap => this;
+
+        public void Map(string name, Expression<Func<T, object>> expr)
+        {
+            Map(expr).Name(name);
+        }
+    }
+
+    public interface ICSVExport
+    {
+        Type Type { get; }
+
+        ICSVClassMap ClassMap { get; }
+
+        IEnumerable<object> Records { get; }
+    }
+
+    public interface ICSVExport<T> : ICSVExport
+        where T : class
+    {
+        new Type Type => typeof(T);
+        new CSVClassMap<T> ClassMap { get; }
+        new IEnumerable<T> Records { get; }
+
+        Type ICSVExport.Type => Type;
+        ICSVClassMap ICSVExport.ClassMap => ClassMap;
+        IEnumerable<object> ICSVExport.Records => Records;
+    }
+
+    public class CSVExport<T> : ICSVExport<T>
+        where T : class
+    {
+        public CSVClassMap<T> ClassMap { get; } = new CSVClassMap<T>();
+
+        public IEnumerable<T> Records => Items;
+
+        public List<T> Items { get; } = new List<T>();
+
+        public void DefineMapping(List<Tuple<string, Expression<Func<T, object>>>> mappings)
+        {
+            foreach(var (name, expr) in mappings)
+            {
+                ClassMap.Map(name, expr);
+            }
+        }
+        public void Map(string name,  Expression<Func<T, object>> expr)
+        {
+            ClassMap.Map(name, expr);
+        }
+
+        public void Add(T item)
+        {
+            Items.Add(item);
+        }
+        public void AddRange(IEnumerable<T> items)
+        {
+            Items.AddRange(items);
+        }
+    }
+
+    /// <summary>
+    /// Defines an interface for posters that can export to CSV.
+    /// </summary>
+    /// <typeparam name="TEntity"></typeparam>
+    public interface ICSVPoster<TEntity> : IPoster<TEntity, CSVPosterSettings<TEntity>>
+        where TEntity : Entity, IPostable
+    {
+        ICSVExport Process(IEnumerable<TEntity> entities);
+    }
+}

+ 19 - 0
InABox.Poster.CSV/InABox.Poster.CSV.csproj

@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+	<PropertyGroup>
+		<TargetFramework>net6.0-windows</TargetFramework>
+		<ImplicitUsings>enable</ImplicitUsings>
+		<Nullable>enable</Nullable>
+		<UseWPF>true</UseWPF>
+	</PropertyGroup>
+
+	<ItemGroup>
+	  <PackageReference Include="CsvHelper" Version="30.0.1" />
+	</ItemGroup>
+
+	<ItemGroup>
+		<ProjectReference Include="..\InABox.Core\InABox.Core.csproj" />
+		<ProjectReference Include="..\inabox.scripting\InABox.Scripting.csproj" />
+	</ItemGroup>
+
+</Project>

+ 0 - 1
InABox.Server/InABox.Server.csproj

@@ -15,7 +15,6 @@
     </ItemGroup>
 
     <ItemGroup>
-        <ProjectReference Include="..\InABox.Configuration\InABox.Configuration.csproj" />
         <ProjectReference Include="..\InABox.Core\InABox.Core.csproj" />
         <ProjectReference Include="..\InABox.Database\InABox.Database.csproj" />
         <ProjectReference Include="..\InABox.IPC.Shared\InABox.IPC.Shared.csproj" />

+ 3 - 3
inabox.scripting/ScriptDocument.cs

@@ -21,14 +21,14 @@ namespace InABox.Scripting
 {
     public class ScriptProperty : Dictionary<string, object>
     {
-        public ScriptProperty(string name, object value)
+        public ScriptProperty(string name, object? value)
         {
             Name = name;
             Value = value;
         }
 
         public string Name { get; set; }
-        public object Value { get; set; }
+        public object? Value { get; set; }
     }
 
     public class CompileException : Exception
@@ -180,7 +180,7 @@ namespace InABox.Scripting
                 prop.Value = value;
         }
 
-        public object GetValue(string name, object defaultvalue = null)
+        public object? GetValue(string name, object? defaultvalue = null)
         {
             var prop = Properties.FirstOrDefault(x => x.Name.Equals(name));
             return prop != null ? prop.Value : defaultvalue;

+ 0 - 1
inabox.wpf/InABox.Wpf.csproj

@@ -119,7 +119,6 @@
 
     <ItemGroup>
         <ProjectReference Include="..\..\3rdpartylibs\roslynpad\src\RoslynPad.Editor.Windows\RoslynPad.Editor.Windows.csproj" />
-        <ProjectReference Include="..\InABox.Configuration\InABox.Configuration.csproj" />
         <ProjectReference Include="..\InABox.Core\InABox.Core.csproj" />
         <ProjectReference Include="..\InABox.Dxf\InABox.Dxf.csproj" />
         <ProjectReference Include="..\InABox.Scripting\InABox.Scripting.csproj" />