From 0e9571fe10f781e7a64514ddee5a78ef7ccd39fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20B=C3=BCchel?= Date: Thu, 6 Jul 2017 10:56:03 +0200 Subject: [PATCH] Continued implementing the scaffolding: - Added composition root - Implemented XML resource for I18n --- .../I18n/{StringsTests.cs => TextTests.cs} | 19 ++++++++-- .../SafeExamBrowser.Core.UnitTests.csproj | 2 +- .../{IStringResource.cs => ITextResource.cs} | 4 +- SafeExamBrowser.Core/I18n/Key.cs | 1 + SafeExamBrowser.Core/I18n/NullTextResource.cs | 21 ++++++++++ .../I18n/{Strings.cs => Text.cs} | 31 ++++++++++++--- SafeExamBrowser.Core/I18n/Text.xml | 1 + SafeExamBrowser.Core/I18n/XmlTextResource.cs | 38 +++++++++++++++++++ .../SafeExamBrowser.Core.csproj | 10 +++-- SafeExamBrowser/App.cs | 31 ++++++++++----- SafeExamBrowser/CompositionRoot.cs | 29 ++++++++++++++ SafeExamBrowser/SafeExamBrowser.csproj | 1 + 12 files changed, 165 insertions(+), 23 deletions(-) rename SafeExamBrowser.Core.UnitTests/I18n/{StringsTests.cs => TextTests.cs} (67%) rename SafeExamBrowser.Core/Contracts/{IStringResource.cs => ITextResource.cs} (84%) create mode 100644 SafeExamBrowser.Core/I18n/NullTextResource.cs rename SafeExamBrowser.Core/I18n/{Strings.cs => Text.cs} (53%) create mode 100644 SafeExamBrowser.Core/I18n/XmlTextResource.cs create mode 100644 SafeExamBrowser/CompositionRoot.cs diff --git a/SafeExamBrowser.Core.UnitTests/I18n/StringsTests.cs b/SafeExamBrowser.Core.UnitTests/I18n/TextTests.cs similarity index 67% rename from SafeExamBrowser.Core.UnitTests/I18n/StringsTests.cs rename to SafeExamBrowser.Core.UnitTests/I18n/TextTests.cs index 1f92811e..1d7a41ca 100644 --- a/SafeExamBrowser.Core.UnitTests/I18n/StringsTests.cs +++ b/SafeExamBrowser.Core.UnitTests/I18n/TextTests.cs @@ -13,21 +13,34 @@ using SafeExamBrowser.Core.I18n; namespace SafeExamBrowser.Core.UnitTests { [TestClass] - public class StringsTests + public class TextTests { + [TestMethod] + public void MustNeverBeNull() + { + Assert.IsNotNull(Text.Instance); + } + [TestMethod] public void MustNeverReturnNull() { - var text = Strings.Get((Key) (-1)); + var text = Text.Instance.Get((Key) (-1)); Assert.IsNotNull(text); } + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void MustNotAllowBeingNull() + { + Text.Instance = null; + } + [TestMethod] [ExpectedException(typeof(ArgumentNullException))] public void MustNotAllowNullResource() { - Strings.Initialize(null); + new Text(null); } } } diff --git a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj index ee138656..be1618ea 100644 --- a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj +++ b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj @@ -48,7 +48,7 @@ - + diff --git a/SafeExamBrowser.Core/Contracts/IStringResource.cs b/SafeExamBrowser.Core/Contracts/ITextResource.cs similarity index 84% rename from SafeExamBrowser.Core/Contracts/IStringResource.cs rename to SafeExamBrowser.Core/Contracts/ITextResource.cs index e9884293..d136df42 100644 --- a/SafeExamBrowser.Core/Contracts/IStringResource.cs +++ b/SafeExamBrowser.Core/Contracts/ITextResource.cs @@ -11,8 +11,8 @@ using SafeExamBrowser.Core.I18n; namespace SafeExamBrowser.Core.Contracts { - public interface IStringResource + public interface ITextResource { - IDictionary LoadStrings(); + IDictionary LoadText(); } } diff --git a/SafeExamBrowser.Core/I18n/Key.cs b/SafeExamBrowser.Core/I18n/Key.cs index 29624617..2a21e2bc 100644 --- a/SafeExamBrowser.Core/I18n/Key.cs +++ b/SafeExamBrowser.Core/I18n/Key.cs @@ -10,6 +10,7 @@ namespace SafeExamBrowser.Core.I18n { public enum Key { + MessageBox_FatalErrorTitle, MessageBox_SingleInstance, MessageBox_SingleInstanceTitle } diff --git a/SafeExamBrowser.Core/I18n/NullTextResource.cs b/SafeExamBrowser.Core/I18n/NullTextResource.cs new file mode 100644 index 00000000..29d64b3f --- /dev/null +++ b/SafeExamBrowser.Core/I18n/NullTextResource.cs @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +using System.Collections.Generic; +using SafeExamBrowser.Core.Contracts; + +namespace SafeExamBrowser.Core.I18n +{ + class NullTextResource : ITextResource + { + public IDictionary LoadText() + { + return new Dictionary(); + } + } +} diff --git a/SafeExamBrowser.Core/I18n/Strings.cs b/SafeExamBrowser.Core/I18n/Text.cs similarity index 53% rename from SafeExamBrowser.Core/I18n/Strings.cs rename to SafeExamBrowser.Core/I18n/Text.cs index 543b6801..bec437c4 100644 --- a/SafeExamBrowser.Core/I18n/Strings.cs +++ b/SafeExamBrowser.Core/I18n/Text.cs @@ -12,21 +12,42 @@ using SafeExamBrowser.Core.Contracts; namespace SafeExamBrowser.Core.I18n { - public static class Strings + public class Text { - private static IDictionary cache = new Dictionary(); + private static Text instance; + private static readonly object @lock = new object(); - public static void Initialize(IStringResource resource) + private IDictionary cache = new Dictionary(); + + public Text(ITextResource resource) { if (resource == null) { throw new ArgumentNullException(nameof(resource)); } - cache = resource.LoadStrings(); + cache = resource.LoadText(); } - public static string Get(Key key) + public static Text Instance + { + get + { + lock (@lock) + { + return instance ?? new Text(new NullTextResource()); + } + } + set + { + lock (@lock) + { + instance = value ?? throw new ArgumentNullException(nameof(value)); + } + } + } + + public string Get(Key key) { return cache.ContainsKey(key) ? cache[key] : $"Could not find string for key '{key}'!"; } diff --git a/SafeExamBrowser.Core/I18n/Text.xml b/SafeExamBrowser.Core/I18n/Text.xml index 5c279b7a..10eec81e 100644 --- a/SafeExamBrowser.Core/I18n/Text.xml +++ b/SafeExamBrowser.Core/I18n/Text.xml @@ -1,5 +1,6 @@  + Fatal Error You can only run one instance of SEB at a time. Startup Not Allowed \ No newline at end of file diff --git a/SafeExamBrowser.Core/I18n/XmlTextResource.cs b/SafeExamBrowser.Core/I18n/XmlTextResource.cs new file mode 100644 index 00000000..72145520 --- /dev/null +++ b/SafeExamBrowser.Core/I18n/XmlTextResource.cs @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml.Linq; +using SafeExamBrowser.Core.Contracts; + +namespace SafeExamBrowser.Core.I18n +{ + public class XmlTextResource : ITextResource + { + public IDictionary LoadText() + { + var assembly = Assembly.GetAssembly(typeof(XmlTextResource)).Location; + var path = Path.GetDirectoryName(assembly) + $@"\{nameof(I18n)}\Text.xml"; + var xml = XDocument.Load(path); + var text = new Dictionary(); + + foreach (var definition in xml.Root.Descendants()) + { + if (Enum.TryParse(definition.Name.LocalName, out Key key)) + { + text[key] = definition.Value; + } + } + + return text; + } + } +} diff --git a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj index 233dc534..cade94a3 100644 --- a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj +++ b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj @@ -40,14 +40,18 @@ - + - + + + - + + Always + \ No newline at end of file diff --git a/SafeExamBrowser/App.cs b/SafeExamBrowser/App.cs index 63b85973..647238df 100644 --- a/SafeExamBrowser/App.cs +++ b/SafeExamBrowser/App.cs @@ -10,7 +10,6 @@ using System; using System.Threading; using System.Windows; using SafeExamBrowser.Core.I18n; -using SafeExamBrowser.UserInterface; namespace SafeExamBrowser { @@ -21,22 +20,36 @@ namespace SafeExamBrowser [STAThread] public static void Main() { - if (mutex.WaitOne(TimeSpan.Zero, true)) + try { - StartApplication(); + var compositionRoot = new CompositionRoot(); + + compositionRoot.InitializeGlobalModules(); + compositionRoot.BuildObjectGraph(); + + StartApplication(compositionRoot.Taskbar); + } + catch (Exception e) + { + MessageBox.Show(e.Message + "\n\n" + e.StackTrace, Text.Instance.Get(Key.MessageBox_FatalErrorTitle)); + } + } + + private static void StartApplication(Window taskbar) + { + if (NoInstanceRunning()) + { + new App().Run(taskbar); } else { - MessageBox.Show(Strings.Get(Key.MessageBox_SingleInstance), Strings.Get(Key.MessageBox_SingleInstanceTitle)); + MessageBox.Show(Text.Instance.Get(Key.MessageBox_SingleInstance), Text.Instance.Get(Key.MessageBox_SingleInstanceTitle)); } } - private static void StartApplication() + private static bool NoInstanceRunning() { - var app = new App(); - var taskbar = new Taskbar(); - - app.Run(taskbar); + return mutex.WaitOne(TimeSpan.Zero, true); } } } diff --git a/SafeExamBrowser/CompositionRoot.cs b/SafeExamBrowser/CompositionRoot.cs new file mode 100644 index 00000000..97a3b6ff --- /dev/null +++ b/SafeExamBrowser/CompositionRoot.cs @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +using System.Windows; +using SafeExamBrowser.Core.I18n; +using SafeExamBrowser.UserInterface; + +namespace SafeExamBrowser +{ + class CompositionRoot + { + public Window Taskbar { get; private set; } + + public void InitializeGlobalModules() + { + Text.Instance = new Text(new XmlTextResource()); + } + + public void BuildObjectGraph() + { + Taskbar = new Taskbar(); + } + } +} diff --git a/SafeExamBrowser/SafeExamBrowser.csproj b/SafeExamBrowser/SafeExamBrowser.csproj index 6fb37193..13d7278c 100644 --- a/SafeExamBrowser/SafeExamBrowser.csproj +++ b/SafeExamBrowser/SafeExamBrowser.csproj @@ -51,6 +51,7 @@ + Code