Changed how services work, updated tests and UML to reflect changes.
Began adding persistence, but untested.
This commit is contained in:
parent
0cf2335aa7
commit
c7fadd8166
13
src/GameServiceWarden.Core/Games/GameServiceAction.cs
Normal file
13
src/GameServiceWarden.Core/Games/GameServiceAction.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using GameServiceWarden.ModuleAPI;
|
||||
|
||||
namespace GameServiceWarden.Core.Games
|
||||
{
|
||||
public struct ServiceAction
|
||||
{
|
||||
public string AssemblyName { get; set; }
|
||||
public string ModuleName { get; set; }
|
||||
public string ServiceName { get; set; }
|
||||
public IGameServiceModule Module { get; set; }
|
||||
public GameServiceActions Action { get; set; }
|
||||
}
|
||||
}
|
16
src/GameServiceWarden.Core/Games/GameServiceActions.cs
Normal file
16
src/GameServiceWarden.Core/Games/GameServiceActions.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace GameServiceWarden.Core.Games
|
||||
{
|
||||
public enum GameServiceActions
|
||||
{
|
||||
|
||||
Start,
|
||||
Stop,
|
||||
AddModule,
|
||||
RemoveModule,
|
||||
CreateService,
|
||||
DeleteService,
|
||||
ExecuteCommand,
|
||||
SetServiceOption,
|
||||
View
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using GameServiceWarden.Core.Preferences;
|
||||
using GameServiceWarden.ModuleAPI;
|
||||
|
||||
namespace GameServiceWarden.Core.Games
|
||||
|
@ -1,50 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using GameServiceWarden.Core.Persistence;
|
||||
using GameServiceWarden.ModuleAPI;
|
||||
|
||||
namespace GameServiceWarden.Core.Games
|
||||
{
|
||||
public class GameServiceManager
|
||||
{
|
||||
private readonly Dictionary<string, GameServiceInfo> services = new Dictionary<string, GameServiceInfo>();
|
||||
private readonly Dictionary<string, Dictionary<string, IGameServiceModule>> modules = new Dictionary<string, Dictionary<string, IGameServiceModule>>();
|
||||
private readonly IPersistentDictionary<GameServiceInfo> services;
|
||||
private readonly IReadOnlyPersistentDictionary<IGameServiceModule> modules;
|
||||
|
||||
public void AddModule(string assemblyName, IGameServiceModule module)
|
||||
public GameServiceManager(IPersistentDictionary<GameServiceInfo> services, IReadOnlyPersistentDictionary<IGameServiceModule> modules)
|
||||
{
|
||||
if (!modules.ContainsKey(assemblyName)) modules.Add(assemblyName, new Dictionary<string, IGameServiceModule>());
|
||||
modules[assemblyName][module.Name] = module;
|
||||
}
|
||||
|
||||
public void RemoveModule(string assemblyName, string moduleName)
|
||||
{
|
||||
if (!modules.ContainsKey(assemblyName) || !modules[assemblyName].ContainsKey(moduleName)) throw new KeyNotFoundException($"No module registered from {assemblyName} named {moduleName}.");
|
||||
modules[assemblyName].Remove(moduleName);
|
||||
if (modules[assemblyName].Count == 0) modules.Remove(assemblyName);
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<string> GetAssemblyNames()
|
||||
{
|
||||
string[] names = new string[modules.Count];
|
||||
modules.Keys.CopyTo(names, 0);
|
||||
return names;
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<string> GetModuleNames(string assembly)
|
||||
{
|
||||
if (!modules.ContainsKey(assembly)) throw new KeyNotFoundException($"No loaded assembly named \"{assembly}\".");
|
||||
string[] names = new string[modules.Count];
|
||||
modules[assembly].Keys.CopyTo(names, 0);
|
||||
return names;
|
||||
|
||||
this.services = services;
|
||||
this.modules = modules;
|
||||
}
|
||||
|
||||
public void CreateService(string serviceName, string assemblyName, string moduleName)
|
||||
{
|
||||
if (!modules.ContainsKey(assemblyName) || !modules[assemblyName].ContainsKey(moduleName)) throw new KeyNotFoundException($"No module registered from \"{assemblyName}\" named \"{moduleName}\".");
|
||||
string moduleID = ToModuleID(assemblyName, moduleName);
|
||||
if (!modules.ContainsKey(moduleID)) throw new KeyNotFoundException($"No module registered from \"{assemblyName}\" named \"{moduleName}\".");
|
||||
if (services.ContainsKey(serviceName)) throw new ArgumentException($"Service of Name \"{serviceName}\" already exists.");
|
||||
|
||||
services.Add(serviceName, new GameServiceInfo(modules[assemblyName][moduleName].CreateGameService(), moduleName, assemblyName));
|
||||
services.Add(serviceName, new GameServiceInfo(modules[moduleID].InstantiateGameService(services.GetPathForKey(serviceName), true), moduleName, assemblyName));
|
||||
}
|
||||
|
||||
public void DeleteService(string serviceName)
|
||||
@ -54,6 +33,11 @@ namespace GameServiceWarden.Core.Games
|
||||
services.Remove(serviceName);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetModuleNames()
|
||||
{
|
||||
return modules.Keys;
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<string> GetServiceNames()
|
||||
{
|
||||
string[] names = new string[services.Count];
|
||||
@ -68,13 +52,6 @@ namespace GameServiceWarden.Core.Games
|
||||
return serviceInfo.GetConfigurableOptions();
|
||||
}
|
||||
|
||||
public bool SetServiceOptionValue(string serviceName, string optionName, string value)
|
||||
{
|
||||
if (!services.ContainsKey(serviceName)) throw new KeyNotFoundException($"Service under name \"{serviceName}\" not found.");
|
||||
if (!services[serviceName].GetConfigurableOptions().Contains(optionName)) throw new KeyNotFoundException($"Option \"{optionName}\" for service \"{serviceName}\" not found.");
|
||||
return services[serviceName].SetConfigurableValue(optionName, value);
|
||||
}
|
||||
|
||||
public string GetServiceOptionValue(string serviceName, string optionName)
|
||||
{
|
||||
if (!services.ContainsKey(serviceName)) throw new KeyNotFoundException($"Service under name \"{serviceName}\" not found.");
|
||||
@ -82,6 +59,13 @@ namespace GameServiceWarden.Core.Games
|
||||
return services[serviceName].GetConfigurableValue(optionName);
|
||||
}
|
||||
|
||||
public bool SetServiceOptionValue(string serviceName, string optionName, string value)
|
||||
{
|
||||
if (!services.ContainsKey(serviceName)) throw new KeyNotFoundException($"Service under name \"{serviceName}\" not found.");
|
||||
if (!services[serviceName].GetConfigurableOptions().Contains(optionName)) throw new KeyNotFoundException($"Option \"{optionName}\" for service \"{serviceName}\" not found.");
|
||||
return services[serviceName].SetConfigurableValue(optionName, value);
|
||||
}
|
||||
|
||||
public ServiceState GetServiceState(string serviceName)
|
||||
{
|
||||
if (!services.ContainsKey(serviceName)) throw new KeyNotFoundException($"Service under name \"{serviceName}\" not found.");
|
||||
@ -111,5 +95,10 @@ namespace GameServiceWarden.Core.Games
|
||||
if (!services.ContainsKey(serviceName)) throw new KeyNotFoundException($"Service under name \"{serviceName}\" not found.");
|
||||
return services[serviceName].ServiceConsoleStream;
|
||||
}
|
||||
|
||||
private string ToModuleID(string assemblyName, string moduleName)
|
||||
{
|
||||
return assemblyName + Path.DirectorySeparatorChar + moduleName;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace GameServiceWarden.Core.Games
|
||||
{
|
||||
public interface IGameServiceExecutioner
|
||||
{
|
||||
void ExecuteAction(ServiceAction action);
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
|
||||
namespace GameServiceWarden.Core.Persistence
|
||||
{
|
||||
public class GeneralPersistentDictionary<V> : IPersistentDictionary<V>, ICollection<KeyValuePair<string, V>>
|
||||
{
|
||||
private readonly string mapDirectory;
|
||||
private readonly IPersistentDictionaryWriter<V> writer;
|
||||
private readonly IPersistentDictionaryReader<V> reader;
|
||||
private readonly GeneralReadOnlyPersistentDictionary<V> readDictionary;
|
||||
|
||||
public GeneralPersistentDictionary(string mapDirectory, IPersistentDictionaryReader<V> reader, IPersistentDictionaryWriter<V> writer)
|
||||
{
|
||||
this.mapDirectory = mapDirectory ?? throw new ArgumentNullException("mapDirectory");
|
||||
this.reader = reader ?? throw new ArgumentNullException("reader");
|
||||
this.readDictionary = new GeneralReadOnlyPersistentDictionary<V>(this.mapDirectory, reader);
|
||||
this.writer = writer ?? throw new ArgumentNullException("writer");
|
||||
}
|
||||
|
||||
public V this[string key] { get { return readDictionary[key]; } set { writer.Write(GetPathForKey(key), value); } }
|
||||
|
||||
public ICollection<string> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<string> keys = Directory.EnumerateFileSystemEntries(mapDirectory);
|
||||
List<string> res = new List<string>();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
if (reader.IsValidValue(GetPathForKey(key))) res.Add(key);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<V> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<string> keys = Keys;
|
||||
List<V> res = new List<V>();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
res.Add(reader.Read(GetPathForKey(key)));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count {get { return readDictionary.Count; } }
|
||||
|
||||
public bool IsReadOnly {get { return false; } }
|
||||
|
||||
public string MapDirectory { get { return mapDirectory; } }
|
||||
|
||||
public void Add(string key, V value)
|
||||
{
|
||||
string path = GetPathForKey(key);
|
||||
if (key == null) throw new ArgumentNullException("key");
|
||||
if (File.Exists(path) || Directory.Exists(path))
|
||||
{
|
||||
if (reader.IsValidValue(path)) throw new ArgumentException($"Key \"{key}\" already exists.");
|
||||
throw new ArgumentException($"Corrupt item at \"{path}\" associated with key \"{key}\".");
|
||||
}
|
||||
writer.Write(GetPathForKey(key), value);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<string,V>>.Add(KeyValuePair<string, V> item)
|
||||
{
|
||||
Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
IEnumerable<string> keys = Keys;
|
||||
foreach (string key in keys)
|
||||
{
|
||||
string path = GetPathForKey(key);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.Delete(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<string, V>>.Contains(KeyValuePair<string, V> item)
|
||||
{
|
||||
string path = GetPathForKey(item.Key);
|
||||
return ContainsKey(item.Key) && readDictionary[item.Key].Equals(item.Value);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return readDictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, V>[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null) throw new ArgumentNullException("array");
|
||||
if (arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex");
|
||||
if (array.Length - arrayIndex < Count) throw new ArgumentException($"The number of elements in this dictionary ({Count}) is greater than the space from arrayIndex to the end of the array ({array.Length - arrayIndex}).");
|
||||
IEnumerator<KeyValuePair<string, V>> pairs = GetEnumerator();
|
||||
for (int i = arrayIndex; i < array.Length; i++)
|
||||
{
|
||||
if (!pairs.MoveNext()) return;
|
||||
array[i] = pairs.Current;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, V>> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<KeyValuePair<string, V>>) readDictionary).GetEnumerator();
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException("key");
|
||||
|
||||
if (!ContainsKey(key)) return false;
|
||||
string path = GetPathForKey(key);
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
Directory.Delete(path);
|
||||
return true;
|
||||
}
|
||||
File.Delete(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, V> item)
|
||||
{
|
||||
return Remove(item.Key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, [MaybeNullWhen(false)] out V value)
|
||||
{
|
||||
return readDictionary.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable) readDictionary).GetEnumerator();
|
||||
}
|
||||
|
||||
public string GetPathForKey(string key)
|
||||
{
|
||||
return mapDirectory + Path.DirectorySeparatorChar + key;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
|
||||
namespace GameServiceWarden.Core.Persistence
|
||||
{
|
||||
public class GeneralReadOnlyPersistentDictionary<V> : IReadOnlyPersistentDictionary<V>, IReadOnlyCollection<KeyValuePair<string, V>>
|
||||
{
|
||||
private readonly string mapDirectory;
|
||||
public string MapDirectory { get { return mapDirectory; } }
|
||||
private IPersistentDictionaryReader<V> reader;
|
||||
|
||||
public GeneralReadOnlyPersistentDictionary(string mapDirectory, IPersistentDictionaryReader<V> reader)
|
||||
{
|
||||
this.mapDirectory = mapDirectory;
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
public V this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return reader.Read(GetPathForKey(key));
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<string> keys = Directory.EnumerateFileSystemEntries(mapDirectory);
|
||||
foreach (string key in keys)
|
||||
{
|
||||
string path = GetPathForKey(key);
|
||||
if ((File.Exists(path) || Directory.Exists(path)) && reader.IsValidValue(path)) yield return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<V> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<string> keys = Directory.EnumerateFileSystemEntries(mapDirectory);
|
||||
foreach (string key in keys)
|
||||
{
|
||||
yield return reader.Read(GetPathForKey(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
IEnumerable<string> keys = Directory.EnumerateFileSystemEntries(mapDirectory);
|
||||
foreach (string key in keys)
|
||||
{
|
||||
string path = GetPathForKey(key);
|
||||
if ((File.Exists(path) || Directory.Exists(path)) && reader.IsValidValue(path)) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException(key);
|
||||
string path = GetPathForKey(key);
|
||||
return (File.Exists(path) || Directory.Exists(path)) && reader.IsValidValue(path);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, V>> GetEnumerator()
|
||||
{
|
||||
IEnumerable<string> keys = Keys;
|
||||
List<KeyValuePair<string, V>> pairs = new List<KeyValuePair<string, V>>();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
pairs.Add(new KeyValuePair<string, V>(key, this[key]));
|
||||
}
|
||||
return pairs.GetEnumerator();
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, [MaybeNullWhen(false)] out V value)
|
||||
{
|
||||
string path = GetPathForKey(key);
|
||||
if (!File.Exists(path) || !Directory.Exists(path) || !reader.IsValidValue(path))
|
||||
{
|
||||
value = default(V);
|
||||
return false;
|
||||
}
|
||||
value = reader.Read(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
public string GetPathForKey(string key)
|
||||
{
|
||||
return mapDirectory + Path.DirectorySeparatorChar + key;
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameServiceWarden.Core.Persistence
|
||||
{
|
||||
public interface IPersistentDictionary<V> : IDictionary<string, V>
|
||||
{
|
||||
string MapDirectory { get; }
|
||||
string GetPathForKey(string key);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace GameServiceWarden.Core.Persistence
|
||||
{
|
||||
public interface IPersistentDictionaryReader<V>
|
||||
{
|
||||
V Read(string path);
|
||||
bool IsValidValue(string path);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace GameServiceWarden.Core.Persistence
|
||||
{
|
||||
public interface IPersistentDictionaryWriter<V>
|
||||
{
|
||||
void Write(string path, V value);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameServiceWarden.Core.Persistence
|
||||
{
|
||||
public interface IReadOnlyPersistentDictionary<V> : IReadOnlyDictionary<string, V>
|
||||
{
|
||||
string MapDirectory { get; }
|
||||
string GetPathForKey(string key);
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace GameServiceWarden.Core.Preferences
|
||||
{
|
||||
[Serializable]
|
||||
public class GeneralPreferences : IPersistable
|
||||
{
|
||||
//XML serialization invariants.
|
||||
private readonly XmlSerializer xmlSerializer;
|
||||
private readonly string APP_DATA_DIR;
|
||||
|
||||
//Preferences stored.
|
||||
public int Port = 8080;
|
||||
public string ListeningIP = IPAddress.Any.ToString();
|
||||
public string ModuleDataPath;
|
||||
|
||||
public GeneralPreferences()
|
||||
{
|
||||
APP_DATA_DIR = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/" + Assembly.GetAssembly(GetType()).GetName().Name + "/";
|
||||
xmlSerializer = new XmlSerializer(GetType());
|
||||
|
||||
this.ModuleDataPath = APP_DATA_DIR + "modules/";
|
||||
Load();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
using (FileStream writer = new FileStream(APP_DATA_DIR + GetType().Name + ".xml", FileMode.OpenOrCreate))
|
||||
{
|
||||
xmlSerializer.Serialize(writer, this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
using (FileStream reader = new FileStream(APP_DATA_DIR + GetType().Name + ".xml", FileMode.Open))
|
||||
{
|
||||
xmlSerializer.Deserialize(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
namespace GameServiceWarden.Core.Preferences
|
||||
{
|
||||
public interface IPersistable
|
||||
{
|
||||
public void Save();
|
||||
public void Load();
|
||||
}
|
||||
}
|
0
src/GameServiceWarden.Core/UI/ConsoleView.cs
Normal file
0
src/GameServiceWarden.Core/UI/ConsoleView.cs
Normal file
10
src/GameServiceWarden.Core/UI/ITextCommand.cs
Normal file
10
src/GameServiceWarden.Core/UI/ITextCommand.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace GameServiceWarden.Core.UI
|
||||
{
|
||||
public interface ITextCommand
|
||||
{
|
||||
string Prefix { get; }
|
||||
string Help{ get; }
|
||||
bool Validate(string input);
|
||||
void Execute(string input);
|
||||
}
|
||||
}
|
@ -1,26 +1,28 @@
|
||||
<mxfile host="65bd71144e" modified="2020-12-28T04:29:17.687Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.52.1 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36" etag="3-G5HDQr3muydbMwkt5P" version="13.10.0" type="embed" pages="2">
|
||||
<mxfile host="65bd71144e" modified="2020-12-29T18:25:57.297Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.52.1 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36" etag="YsJOF2puyTwjZNHuS3ue" version="13.10.0" type="embed" pages="2">
|
||||
<diagram id="LHR7ubqCPd17_LyHkaH9" name="Structure">
|
||||
<mxGraphModel dx="1298" dy="740" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-10" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;sketch=1;" parent="1" source="dmd0HlDYcxYugIlahWj0-5" target="dmd0HlDYcxYugIlahWj0-9" edge="1">
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-10" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;dashed=1;endArrow=block;endFill=0;sketch=1;" parent="1" source="dmd0HlDYcxYugIlahWj0-5" target="dmd0HlDYcxYugIlahWj0-9" edge="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-5" value="GameServiceInfo" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="762" y="1030" width="401" height="400" as="geometry"/>
|
||||
<mxGeometry x="762" y="1030" width="401" height="386" as="geometry">
|
||||
<mxRectangle x="762" y="1030" width="130" height="26" as="alternateBounds"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-6" value="- serviceName: string - controlLock: object - state: ServiceState - service: IGameService - serviceConsoleStream: Stream - moduleName: string - assemblyName: string - Dictionary<string, IConfigurable> - disposed: bool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-5" vertex="1">
|
||||
<mxGeometry y="26" width="401" height="154" as="geometry"/>
|
||||
<mxGeometry y="26" width="401" height="140" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-7" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-5" vertex="1">
|
||||
<mxGeometry y="180" width="401" height="8" as="geometry"/>
|
||||
<mxGeometry y="166" width="401" height="8" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-8" value="+ Start(): void + Stop(): void + GetConfigurableOptions(): ISet<string> + SetConfigurableValue(configurationName: string, value: string): bool + GetConfigurableValue(configurationName: string): string + GetServiceState(): ServiceState + getModuleName(): string + GetassemblyName(): string + SetServiceName(name: string): void // Implemented as property + GetServiceName(): string // Implemented as property + GetServiceConsoleStream(): Stream // Implemented as property - OnServiceStateChange(curr: ServiceState, prev: ServiceState): void # Dispose(disposing: bool): void + Dispose(): voide" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-5" vertex="1">
|
||||
<mxGeometry y="188" width="401" height="212" as="geometry"/>
|
||||
<mxGeometry y="174" width="401" height="212" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-9" value="«interface»<br><span>IDisposable</span>" style="html=1;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1260" y="958" width="111" height="50" as="geometry"/>
|
||||
<mxGeometry x="1250" y="980" width="111" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-15" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="1" source="dmd0HlDYcxYugIlahWj0-11" target="dmd0HlDYcxYugIlahWj0-5" edge="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
@ -41,42 +43,18 @@
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-11" value="GameServiceManager" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="722" y="670" width="481" height="280" as="geometry">
|
||||
<mxGeometry x="697" y="640" width="531" height="300" as="geometry">
|
||||
<mxRectangle x="25" y="490" width="120" height="26" as="alternateBounds"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-12" value="- services: Dictionary<string, Service> - modules: Dictionary<string, Dictionary<string, IGameServiceModule>>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-11" vertex="1">
|
||||
<mxGeometry y="26" width="481" height="44" as="geometry"/>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-12" value="- serviceDir: string - services: IDictionary<string, Service> - modules: IReadOnlyDictionary<string, Dictionary<string, IGameServiceModule>>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-11" vertex="1">
|
||||
<mxGeometry y="26" width="531" height="54" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-13" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-11" vertex="1">
|
||||
<mxGeometry y="70" width="481" height="8" as="geometry"/>
|
||||
<mxGeometry y="80" width="531" height="8" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-14" value="+ AddModule(assemblyName: string, module: IGameServiceModule): void + RemoveModule(assemblyName: string, moduleName string): void + CreateService(serviceName: string, assemblyName: string, moduleName: string): void + DeleteService(serviceName: string): void + GetServiceNames(): IReadOnlyCollection<string> + GetServiceOptionsValue(serviceName: string): IEnumerable<string> + SetServiceOptionValue(serviceName: string, optionName: string, string: value): bool + GetServiceState(serviceName: string): ServiceState + StartService(serviceName: string): void + StopService(serviceName: string): void + ExecuteCommand(serviceName: string, command: string): void + GetServiceConsoleStream(): Stream + ExecuteServiceAction(serviceAction: serviceAction): void" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-11" vertex="1">
|
||||
<mxGeometry y="78" width="481" height="202" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-16" value="GameModuleLoader" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1700" y="490" width="460" height="140" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-17" value="- dataDirectory: string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-16" vertex="1">
|
||||
<mxGeometry y="26" width="460" height="26" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-18" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-16" vertex="1">
|
||||
<mxGeometry y="52" width="460" height="8" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-19" value="- InstantiateServiceables(assembly: Assembly): void - LoadAssembly(path: string): void + LoadModules(path: string): IEnumerable<IGameServiceModule> + LoadAllModules(path: string[]): IEnumerable<IGameServiceModule> + LoadAllModules(path: IEnumerable<string>): IEnumerable<IGameServiceModule>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-16" vertex="1">
|
||||
<mxGeometry y="60" width="460" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-20" value="GameServiceGateway" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="2190" y="490" width="440" height="130" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-21" value="- dataDirectory: string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-20" vertex="1">
|
||||
<mxGeometry y="26" width="440" height="26" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-22" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-20" vertex="1">
|
||||
<mxGeometry y="52" width="440" height="8" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-23" value="+ SaveService(name: string, assemblyName: string, moduleName: string): void + GetServiceName(path: string): string + GetServiceModuleName(path: string): string + GetAllServiceInfoPaths() IEnumerable<string>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-20" vertex="1">
|
||||
<mxGeometry y="60" width="440" height="70" as="geometry"/>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-14" value="+ CreateService(serviceName: string, assemblyName: string, moduleName: string): void + DeleteService(serviceName: string): void + GetModuleIDs(): IEnumerable<string> + GetServiceNames(): IReadOnlyCollection<string> + GetServiceOptions(serviceName: string): IEnumerable<string> + GetServiceOptionsValue(serviceName: string): IEnumerable<string> + SetServiceOptionValue(serviceName: string, optionName: string, string: value): bool + GetServiceState(serviceName: string): ServiceState + StartService(serviceName: string): void + StopService(serviceName: string): void + ExecuteCommand(serviceName: string, command: string): void + GetServiceConsoleStream(): Stream + ExecuteServiceAction(serviceAction: serviceAction): void - ToModuleID(assemblyName: string, moduleName: string): string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="dmd0HlDYcxYugIlahWj0-11" vertex="1">
|
||||
<mxGeometry y="88" width="531" height="212" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="dmd0HlDYcxYugIlahWj0-38" value="<<Interface>> ITextCommand" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=40;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1285" y="138" width="181" height="114" as="geometry"/>
|
||||
@ -108,7 +86,7 @@
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="qpeZJq-dxPH0P0VpmRa_-7" value="MainController" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1505" y="220" width="270" height="60" as="geometry"/>
|
||||
<mxGeometry x="1560" y="247" width="270" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="qpeZJq-dxPH0P0VpmRa_-8" value="+ commands: Dictionary<string, ITextCommand>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="qpeZJq-dxPH0P0VpmRa_-7" vertex="1">
|
||||
<mxGeometry y="26" width="270" height="26" as="geometry"/>
|
||||
@ -125,32 +103,32 @@
|
||||
<mxCell id="V3nv0dmUtDNsDw_gxP-z-3" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="1" source="K1k0_LUP-qlT_3mlrptx-2" target="dmd0HlDYcxYugIlahWj0-38" edge="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="K1k0_LUP-qlT_3mlrptx-2" value="GameServiceController" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1255" y="320" width="241" height="60" as="geometry"/>
|
||||
<mxCell id="K1k0_LUP-qlT_3mlrptx-2" value="ConsoleGameServiceController" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1230.5" y="318" width="290" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="K1k0_LUP-qlT_3mlrptx-3" value="- serviceManipulator: IServiceManipulator" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="K1k0_LUP-qlT_3mlrptx-2" vertex="1">
|
||||
<mxGeometry y="26" width="241" height="26" as="geometry"/>
|
||||
<mxCell id="K1k0_LUP-qlT_3mlrptx-3" value="- service: IGameServiceActionExecuter" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="K1k0_LUP-qlT_3mlrptx-2" vertex="1">
|
||||
<mxGeometry y="26" width="290" height="26" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="K1k0_LUP-qlT_3mlrptx-4" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;sketch=1;" parent="K1k0_LUP-qlT_3mlrptx-2" vertex="1">
|
||||
<mxGeometry y="52" width="241" height="8" as="geometry"/>
|
||||
<mxGeometry y="52" width="290" height="8" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="wwlaSBDwwZOn0hO83bWU-16" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="1" source="wwlaSBDwwZOn0hO83bWU-2" target="wwlaSBDwwZOn0hO83bWU-12" edge="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="wwlaSBDwwZOn0hO83bWU-2" value="<<Interface>> IGameServiceActionExecuter" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=40;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1275" y="480" width="201" height="74" as="geometry"/>
|
||||
<mxGeometry x="1275" y="480" width="250" height="74" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="wwlaSBDwwZOn0hO83bWU-4" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;sketch=1;" parent="wwlaSBDwwZOn0hO83bWU-2" vertex="1">
|
||||
<mxGeometry y="40" width="201" height="8" as="geometry"/>
|
||||
<mxGeometry y="40" width="250" height="8" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="wwlaSBDwwZOn0hO83bWU-5" value="+ Manipulate(action: ServiceAction): void" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="wwlaSBDwwZOn0hO83bWU-2" vertex="1">
|
||||
<mxGeometry y="48" width="201" height="26" as="geometry"/>
|
||||
<mxCell id="wwlaSBDwwZOn0hO83bWU-5" value="+ ExecuteAction(action: ServiceAction): void" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="wwlaSBDwwZOn0hO83bWU-2" vertex="1">
|
||||
<mxGeometry y="48" width="250" height="26" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="SI3d9EEbteElKQB4Ic5T-15" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="1" source="wwlaSBDwwZOn0hO83bWU-12" target="SI3d9EEbteElKQB4Ic5T-10" edge="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="wwlaSBDwwZOn0hO83bWU-12" value="<<DS>> GameServiceAction" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=40;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1466" y="600" width="161" height="128" as="geometry"/>
|
||||
<mxGeometry x="1440" y="606" width="161" height="128" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="wwlaSBDwwZOn0hO83bWU-13" value="+ AssemblyName: string + ModuleName: string + ServiceName: string + Module: IModule + Action: ServiceActions" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="wwlaSBDwwZOn0hO83bWU-12" vertex="1">
|
||||
<mxGeometry y="40" width="161" height="80" as="geometry"/>
|
||||
@ -177,7 +155,7 @@
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="HUSvFZX5SimreebZp30a-5" value="MainPresenter" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="30" y="214" width="270" height="60" as="geometry"/>
|
||||
<mxGeometry x="20" y="214" width="270" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="HUSvFZX5SimreebZp30a-6" value="- textPresenters: Dictionary<string, ITextOutput>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="HUSvFZX5SimreebZp30a-5" vertex="1">
|
||||
<mxGeometry y="26" width="270" height="26" as="geometry"/>
|
||||
@ -219,360 +197,360 @@
|
||||
<mxGeometry y="130" width="365" height="8" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="SI3d9EEbteElKQB4Ic5T-10" value="<<Enum>> GameServiceActions" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=40;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;sketch=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="882.5" y="420" width="160" height="188" as="geometry"/>
|
||||
<mxGeometry x="882.5" y="408" width="160" height="198" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="SI3d9EEbteElKQB4Ic5T-11" value="+ Start + Stop + AddModule + RemoveModule + CreateService + DeleteService + Execute + SetServiceOption + View" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="SI3d9EEbteElKQB4Ic5T-10" vertex="1">
|
||||
<mxGeometry y="40" width="160" height="140" as="geometry"/>
|
||||
<mxCell id="SI3d9EEbteElKQB4Ic5T-11" value="+ Start + Stop + AddModule + RemoveModule + CreateService + DeleteService + ExecuteCommand + SetServiceOption + RestoreService + View" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;sketch=1;" parent="SI3d9EEbteElKQB4Ic5T-10" vertex="1">
|
||||
<mxGeometry y="40" width="160" height="150" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="SI3d9EEbteElKQB4Ic5T-12" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;sketch=1;" parent="SI3d9EEbteElKQB4Ic5T-10" vertex="1">
|
||||
<mxGeometry y="180" width="160" height="8" as="geometry"/>
|
||||
<mxGeometry y="190" width="160" height="8" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
<diagram id="gj0qHRc3eh050ABAey3g" name="Data-Flow">
|
||||

 


|
||||
<mxGraphModel dx="1009" dy="418" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||

 


|
||||

 
 



|
||||
<mxGraphModel dx="1216" dy="740" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||

 
 



|
||||
<root>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-0"/>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-1" parent="jVG6p58vlRYGO9X4wXeX-0"/>
|
||||

 


|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-2" target="jVG6p58vlRYGO9X4wXeX-3" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-21" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-2" target="jVG6p58vlRYGO9X4wXeX-3" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-2" value="Actor" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry x="10" y="300" width="30" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-3" target="jVG6p58vlRYGO9X4wXeX-4" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-12" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-3" target="jVG6p58vlRYGO9X4wXeX-4" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=0.75;entryY=0.1;entryDx=0;entryDy=0;entryPerimeter=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-3" target="jVG6p58vlRYGO9X4wXeX-2" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-22" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=0.75;entryY=0.1;entryDx=0;entryDy=0;entryPerimeter=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-3" target="jVG6p58vlRYGO9X4wXeX-2" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="345FJoVc2gbAayMsQlD7-0" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-3" target="jVG6p58vlRYGO9X4wXeX-4" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="345FJoVc2gbAayMsQlD7-6" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-3" target="28FAlPysTx9DMYvLwa-2-7" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-3" value="Console View" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-3" value="Console View" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="80" y="300" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-4" target="jVG6p58vlRYGO9X4wXeX-5" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-13" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-4" target="jVG6p58vlRYGO9X4wXeX-5" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="345FJoVc2gbAayMsQlD7-2" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-4" target="jVG6p58vlRYGO9X4wXeX-5" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-4" value="string command (request)" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-4" value="string command (request)" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="260" y="482.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-5" target="jVG6p58vlRYGO9X4wXeX-7" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-8" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-5" target="jVG6p58vlRYGO9X4wXeX-7" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-3" value="Use" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;endArrow=open;endFill=0;dashed=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-5" target="jVG6p58vlRYGO9X4wXeX-7" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-3" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;endArrow=open;endFill=0;dashed=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-5" target="jVG6p58vlRYGO9X4wXeX-7" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-18" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;strokeColor=#006EAF;fillColor=#1ba1e2;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-5" target="jVG6p58vlRYGO9X4wXeX-9" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-5" value="MainController" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-5" value="MainController" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="420" y="482.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-6" value="http://www.plainionist.net/Implementing-Clean-Architecture-Controller-Presenter/" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-6" value="http://www.plainionist.net/Implementing-Clean-Architecture-Controller-Presenter/" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry y="840" width="480" height="20" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-7" value="&lt;&lt;Interface&gt;&gt;<br>ICommand" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-7" value="&lt;&lt;Interface&gt;&gt;<br>ICommand" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="420" y="372.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-9" target="jVG6p58vlRYGO9X4wXeX-7" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-10" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-9" target="jVG6p58vlRYGO9X4wXeX-7" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-8" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;endArrow=open;endFill=0;strokeColor=#006EAF;fillColor=#1ba1e2;exitX=1;exitY=0.5;exitDx=0;exitDy=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-9" target="UY-EM7-1ECCvWtENr50b-1" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry">
|
||||

 


|
||||

 
 



|
||||
<mxPoint x="809.9999999999998" y="512.5000000000002" as="sourcePoint"/>
|
||||

 


|
||||

 
 



|
||||
</mxGeometry>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="345FJoVc2gbAayMsQlD7-3" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-9" target="UY-EM7-1ECCvWtENr50b-2" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="345FJoVc2gbAayMsQlD7-4" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="jVG6p58vlRYGO9X4wXeX-9" target="UY-EM7-1ECCvWtENr50b-1" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-9" value="ServiceController" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="jVG6p58vlRYGO9X4wXeX-9" value="ServiceController" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="575" y="482.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;endFill=1;strokeColor=none;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-1" target="UY-EM7-1ECCvWtENr50b-2" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-4" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=block;endFill=1;strokeColor=none;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-1" target="UY-EM7-1ECCvWtENr50b-2" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-5" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;strokeColor=#f0f0f0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-1" target="UY-EM7-1ECCvWtENr50b-2" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-7" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1.008;entryY=0.625;entryDx=0;entryDy=0;entryPerimeter=0;endArrow=open;endFill=0;strokeColor=#f0f0f0;dashed=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-1" target="UY-EM7-1ECCvWtENr50b-1" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry">
|
||||

 


|
||||

 
 



|
||||
<Array as="points">
|
||||

 


|
||||

 
 



|
||||
<mxPoint x="960" y="338"/>
|
||||

 


|
||||

 
 



|
||||
<mxPoint x="960" y="580"/>
|
||||

 


|
||||

 
 



|
||||
</Array>
|
||||

 


|
||||

 
 



|
||||
</mxGeometry>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-16" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=open;endFill=0;dashed=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-1" target="UY-EM7-1ECCvWtENr50b-11" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="345FJoVc2gbAayMsQlD7-7" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-1" target="UY-EM7-1ECCvWtENr50b-10" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry">
|
||||

 


|
||||

 
 



|
||||
<Array as="points">
|
||||

 


|
||||

 
 



|
||||
<mxPoint x="960" y="338"/>
|
||||

 


|
||||

 
 



|
||||
<mxPoint x="960" y="83"/>
|
||||

 


|
||||

 
 



|
||||
</Array>
|
||||

 


|
||||

 
 



|
||||
</mxGeometry>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-1" value="ServiceManager" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-1" value="ServiceManager" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="800" y="307.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-5" target="tM_Gde3HH8YiZ2frBV5J-0" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-9" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-5" target="tM_Gde3HH8YiZ2frBV5J-0" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-12" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=block;endFill=0;strokeColor=#f0f0f0;dashed=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-5" target="UY-EM7-1ECCvWtENr50b-11" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-13" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=open;endFill=0;strokeColor=#f0f0f0;dashed=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-5" target="UY-EM7-1ECCvWtENr50b-10" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-3" style="edgeStyle=orthogonalEdgeStyle;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-5" target="tM_Gde3HH8YiZ2frBV5J-1" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-3" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-5" target="tM_Gde3HH8YiZ2frBV5J-1" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-5" value="ServicePresenter" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-5" value="ServicePresenter" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="575" y="122.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-7" target="jVG6p58vlRYGO9X4wXeX-3" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-8" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=open;endFill=0;fillColor=#1ba1e2;strokeColor=#006EAF;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-7" target="jVG6p58vlRYGO9X4wXeX-3" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-5" value="Use" style="edgeStyle=orthogonalEdgeStyle;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-7" target="tM_Gde3HH8YiZ2frBV5J-0" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-5" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-7" target="tM_Gde3HH8YiZ2frBV5J-0" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-7" value="String Output" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="28FAlPysTx9DMYvLwa-2-7" value="String Output" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="260" y="122.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-1" value="ServiceAction &lt;DS&gt;" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-1" value="ServiceAction &lt;DS&gt;" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="800" y="542.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-6" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=open;endFill=0;strokeColor=#f0f0f0;dashed=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="UY-EM7-1ECCvWtENr50b-2" target="UY-EM7-1ECCvWtENr50b-1" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-20" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;endArrow=open;endFill=0;strokeColor=#006EAF;fillColor=#1ba1e2;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="UY-EM7-1ECCvWtENr50b-1" target="28FAlPysTx9DMYvLwa-2-1" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-2" value="&lt;&lt;Interface&gt;&gt;<br>IServiceManipulator" style="rounded=0;whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-2" value="&lt;&lt;Interface&gt;&gt;<br>IServiceManipulator" style="whiteSpace=wrap;html=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="800" y="432.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-22" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;endArrow=open;endFill=0;strokeColor=#006EAF;fillColor=#1ba1e2;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="UY-EM7-1ECCvWtENr50b-10" target="28FAlPysTx9DMYvLwa-2-5" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-10" value="ServicesResult &lt;DS&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-10" value="ServicesResult &lt;DS&gt;" style="whiteSpace=wrap;html=1;fillColor=none;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="800" y="67.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-14" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;endArrow=open;endFill=0;strokeColor=#f0f0f0;dashed=1;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="UY-EM7-1ECCvWtENr50b-11" target="UY-EM7-1ECCvWtENr50b-10" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-21" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;endArrow=open;endFill=0;strokeColor=#006EAF;fillColor=#1ba1e2;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="28FAlPysTx9DMYvLwa-2-1" target="UY-EM7-1ECCvWtENr50b-10" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-11" value="&lt;&lt;Interface&gt;&gt;<br>IServicesMonitor" style="rounded=0;whiteSpace=wrap;html=1;fillColor=none;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-11" value="&lt;&lt;Interface&gt;&gt;<br>IServicesMonitor" style="whiteSpace=wrap;html=1;fillColor=none;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry x="800" y="167.5" width="120" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-70" value="" style="line;strokeWidth=2;direction=south;html=1;fillColor=none;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry x="220" y="50" width="10" height="570" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-71" value="" style="line;strokeWidth=2;direction=south;html=1;fillColor=none;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry x="760" y="50" width="10" height="570" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-73" value="Page 191 (Chapter 22) of Clean Architecture" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="UY-EM7-1ECCvWtENr50b-73" value="Page 191 (Chapter 22) of Clean Architecture" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 
 



|
||||
<mxGeometry y="870" width="480" height="20" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-2" style="edgeStyle=orthogonalEdgeStyle;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;" parent="jVG6p58vlRYGO9X4wXeX-1" source="tM_Gde3HH8YiZ2frBV5J-0" target="tM_Gde3HH8YiZ2frBV5J-1" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-2" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;endArrow=block;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="tM_Gde3HH8YiZ2frBV5J-0" target="tM_Gde3HH8YiZ2frBV5J-1" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-4" value="Use" style="edgeStyle=orthogonalEdgeStyle;sketch=1;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;" parent="jVG6p58vlRYGO9X4wXeX-1" source="tM_Gde3HH8YiZ2frBV5J-0" target="tM_Gde3HH8YiZ2frBV5J-1" edge="1">
|
||||

 


|
||||

 
 



|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-4" value="Use" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;dashed=1;endArrow=open;endFill=0;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" source="tM_Gde3HH8YiZ2frBV5J-0" target="tM_Gde3HH8YiZ2frBV5J-1" edge="1">
|
||||

 
 



|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-0" value="MainPresenter" style="html=1;dashed=0;whitespace=wrap;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry x="420" y="122.5" width="110" height="60" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
<mxCell id="tM_Gde3HH8YiZ2frBV5J-1" value="&lt;&lt;Interface&gt;&gt;<br>IConsoleOutput" style="html=1;dashed=0;whitespace=wrap;sketch=1;" parent="jVG6p58vlRYGO9X4wXeX-1" vertex="1">
|
||||

 


|
||||

 
 



|
||||
<mxGeometry x="420" y="20" width="110" height="50" as="geometry"/>
|
||||

 


|
||||

 
 



|
||||
</mxCell>
|
||||

 


|
||||

 
 



|
||||
</root>
|
||||

 


|
||||

 
 



|
||||
</mxGraphModel>
|
||||

 


|
||||

 
 



|
||||
</diagram>
|
||||
</mxfile>
|
@ -22,7 +22,9 @@ namespace GameServiceWarden.ModuleAPI
|
||||
/// <summary>
|
||||
/// Creates an instance of a the service to be used.
|
||||
/// </summary>
|
||||
/// <param name="workspace">The workspace directory. All service required files should be stored here. Expect the directory to be created.</param>
|
||||
/// <param name="clean">Whether or not this game service is new. That is, the <code>workspace</code> can be assumed empty.</param>
|
||||
/// <returns>The <see cref="IGameService"/> responsible for the instance of the game service.</returns>
|
||||
IGameService CreateGameService();
|
||||
IGameService InstantiateGameService(string workspace, bool clean);
|
||||
}
|
||||
}
|
@ -21,5 +21,10 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
{
|
||||
return new FakeGameService(configurables);
|
||||
}
|
||||
|
||||
public IGameService InstantiateGameService(string workspace, bool clean)
|
||||
{
|
||||
return new FakeGameService(configurables);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using GameServiceWarden.Core.Persistence;
|
||||
|
||||
namespace GameServiceWarden.Core.Tests.Modules
|
||||
{
|
||||
public class FakePersistentDictionary<V> : IPersistentDictionary<V>, IReadOnlyPersistentDictionary<V>
|
||||
{
|
||||
private IDictionary<string, V> backing = new Dictionary<string, V>();
|
||||
public V this[string key] { get { return backing[key]; } set { backing[key] = value; } }
|
||||
|
||||
public string MapDirectory { get { return "fake/directory/"; } }
|
||||
|
||||
public ICollection<string> Keys { get { return backing.Keys; } }
|
||||
|
||||
public ICollection<V> Values { get { return backing.Values; } }
|
||||
|
||||
public int Count { get { return backing.Count; } }
|
||||
|
||||
public bool IsReadOnly { get { return false; } }
|
||||
|
||||
IEnumerable<string> IReadOnlyDictionary<string, V>.Keys { get { return backing.Keys; } }
|
||||
|
||||
IEnumerable<V> IReadOnlyDictionary<string, V>.Values { get { return backing.Values; } }
|
||||
|
||||
public void Add(string key, V value)
|
||||
{
|
||||
backing.Add(key, value);
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, V> item)
|
||||
{
|
||||
backing.Add(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
backing.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, V> item)
|
||||
{
|
||||
return backing.Contains(item);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return backing.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, V>[] array, int arrayIndex)
|
||||
{
|
||||
backing.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, V>> GetEnumerator()
|
||||
{
|
||||
return backing.GetEnumerator();
|
||||
}
|
||||
|
||||
public string GetPathForKey(string key)
|
||||
{
|
||||
return MapDirectory + Path.DirectorySeparatorChar + key;
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
return backing.Remove(key);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, V> item)
|
||||
{
|
||||
return backing.Remove(item);
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, [MaybeNullWhen(false)] out V value)
|
||||
{
|
||||
return backing.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return backing.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
@ -7,33 +7,6 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
{
|
||||
public class GameServiceManagerTest
|
||||
{
|
||||
[Fact]
|
||||
public void AddModule_NewManager_SuccessfulAddition()
|
||||
{
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
//Then
|
||||
Assert.Contains<string>(ASSEMBLY_NAME, serviceManager.GetAssemblyNames());
|
||||
Assert.Contains<string>(stubGameServiceModule.Name, serviceManager.GetModuleNames(ASSEMBLY_NAME));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveModule_NewManager_SuccessfulRemoval()
|
||||
{
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
serviceManager.RemoveModule(ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
//Then
|
||||
Assert.DoesNotContain<string>(ASSEMBLY_NAME, serviceManager.GetAssemblyNames());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateService_NewManager_NewServiceCreated()
|
||||
@ -41,11 +14,13 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string FAKE_SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
//When
|
||||
serviceManager.CreateService("FakeService", ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(FAKE_SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
//Then
|
||||
Assert.Contains<string>(FAKE_SERVICE_NAME, serviceManager.GetServiceNames());
|
||||
}
|
||||
@ -56,11 +31,13 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string FAKE_SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
serviceManager.CreateService(FAKE_SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
//When
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(FAKE_SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
serviceManager.DeleteService(FAKE_SERVICE_NAME);
|
||||
//Then
|
||||
Assert.DoesNotContain<string>(FAKE_SERVICE_NAME, serviceManager.GetServiceNames());
|
||||
@ -72,10 +49,12 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string FAKE_SERVICE_PREFIX = "FakeService_";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
serviceManager.CreateService(FAKE_SERVICE_PREFIX + i, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
@ -93,14 +72,16 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule(
|
||||
new FakeGameConfigurable("A"),
|
||||
new FakeGameConfigurable("B"),
|
||||
new FakeGameConfigurable("C")
|
||||
);
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
//Then
|
||||
Assert.Contains<string>("A", serviceManager.GetServiceOptions(SERVICE_NAME));
|
||||
@ -114,12 +95,14 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule(
|
||||
new FakeGameConfigurable("A")
|
||||
);
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
serviceManager.SetServiceOptionValue(SERVICE_NAME, "A", "Test");
|
||||
//Then
|
||||
@ -132,10 +115,12 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
//Then
|
||||
Assert.Equal<ServiceState>(ServiceState.Stopped, serviceManager.GetServiceState(SERVICE_NAME));
|
||||
@ -147,10 +132,12 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
serviceManager.StartService(SERVICE_NAME);
|
||||
//Then
|
||||
@ -163,10 +150,12 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
serviceManager.StartService(SERVICE_NAME);
|
||||
//Then
|
||||
@ -179,10 +168,12 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
serviceManager.StartService(SERVICE_NAME);
|
||||
serviceManager.StopService(SERVICE_NAME);
|
||||
@ -196,10 +187,12 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
serviceManager.StartService(SERVICE_NAME);
|
||||
serviceManager.ExecuteCommand(SERVICE_NAME, "Test");
|
||||
@ -218,10 +211,12 @@ namespace GameServiceWarden.Core.Tests.Modules.Games
|
||||
//Given
|
||||
const string ASSEMBLY_NAME = "FakeAssembly";
|
||||
const string SERVICE_NAME = "FakeService";
|
||||
GameServiceManager serviceManager = new GameServiceManager();
|
||||
FakePersistentDictionary<IGameServiceModule> stubPersistentModuleDictionary = new FakePersistentDictionary<IGameServiceModule>();
|
||||
FakePersistentDictionary<GameServiceInfo> stubPersistentServiceDictionary = new FakePersistentDictionary<GameServiceInfo>();
|
||||
GameServiceManager serviceManager = new GameServiceManager(stubPersistentServiceDictionary, stubPersistentModuleDictionary);
|
||||
IGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
|
||||
//When
|
||||
serviceManager.AddModule(ASSEMBLY_NAME, stubGameServiceModule);
|
||||
stubPersistentModuleDictionary.Add(ASSEMBLY_NAME + Path.DirectorySeparatorChar + stubGameServiceModule.Name, stubGameServiceModule);
|
||||
serviceManager.CreateService(SERVICE_NAME, ASSEMBLY_NAME, stubGameServiceModule.Name);
|
||||
//Then
|
||||
Assert.Null(serviceManager.GetServiceConsoleStream(SERVICE_NAME));
|
||||
|
Reference in New Issue
Block a user