diff --git a/.gitignore b/.gitignore index 668b6b0..cabb36a 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,8 @@ /Voile.Storage.Oracle/obj /Voile.Storage.Postgresql/obj /Voile.Storage.SqlServer/obj +/Voile.Common/bin +/Voile.Common/obj +/Voile.Common.Tests/bin +/Voile.Common.Tests/obj +/.idea diff --git a/Voile.Common.Tests/DemoAssets/AutoconfigSource.cs b/Voile.Common.Tests/DemoAssets/AutoconfigSource.cs new file mode 100644 index 0000000..78ca286 --- /dev/null +++ b/Voile.Common.Tests/DemoAssets/AutoconfigSource.cs @@ -0,0 +1,51 @@ +using Voile.Common.Configuration; + +namespace Voile.Common.Tests.DemoAssets; + +public class AutoconfigSource : IConfigurationSource +{ + public bool ReadValue(string category, string key, bool defaultVaule) + { + return true; + } + + public object ReadValue(string category, string key, float defaultVaule) + { + throw new NotImplementedException(); + } + + public int ReadValue(string category, string key, int defaultVaule) + { + return 2; + } + + public string ReadValue(string category, string key, string defaultVaule) + { + return "Three"; + } + + public void WriteValue(string category, string key, bool value) + { + throw new NotImplementedException(); + } + + public void WriteValue(string category, string key, long value) + { + throw new NotImplementedException(); + } + + public void WriteValue(string category, string key, int value) + { + throw new NotImplementedException(); + } + + public void WriteValue(string category, string key, string value) + { + throw new NotImplementedException(); + } + + public void WriteValue(string category, string key, float value) + { + throw new NotImplementedException(); + } +} diff --git a/Voile.Common.Tests/DemoAssets/AutoconfigurableObject.cs b/Voile.Common.Tests/DemoAssets/AutoconfigurableObject.cs new file mode 100644 index 0000000..bb941bd --- /dev/null +++ b/Voile.Common.Tests/DemoAssets/AutoconfigurableObject.cs @@ -0,0 +1,15 @@ +using Voile.Common.Reflection; + +namespace Voile.Common.Tests.DemoAssets; + +public class AutoconfigurableObject +{ + [Autoconfigurable] + public bool BooleanValue { get; set; } + + [Autoconfigurable] + public int IntegerValue { get; set; } + + [Autoconfigurable] + public string StringValue { get; set; } +} diff --git a/Voile.Common/Configuration/IConfigurationSource.cs b/Voile.Common/Configuration/IConfigurationSource.cs new file mode 100644 index 0000000..3af19f3 --- /dev/null +++ b/Voile.Common/Configuration/IConfigurationSource.cs @@ -0,0 +1,16 @@ +namespace Voile.Common.Configuration; + +public interface IConfigurationSource +{ + + public bool ReadValue(string category, string key, bool defaultVaule); + public object ReadValue(string category, string key, float defaultVaule); + public int ReadValue(string category, string key, int defaultVaule); + public string ReadValue(string category, string key, string defaultVaule); + + public void WriteValue(string category, string key, bool value); + public void WriteValue(string category, string key, long value); + public void WriteValue(string category, string key, int value); + public void WriteValue(string category, string key, string value); + public void WriteValue(string category, string key, float value); +} diff --git a/Voile.Common/DRM/NeedsEntitlementAttribute.cs b/Voile.Common/DRM/NeedsEntitlementAttribute.cs new file mode 100644 index 0000000..1144732 --- /dev/null +++ b/Voile.Common/DRM/NeedsEntitlementAttribute.cs @@ -0,0 +1,12 @@ +namespace Voile.Common.DRM; + +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] +public sealed class NeedsEntitlementAttribute : Attribute +{ + public NeedsEntitlementAttribute(string guid) + { + this.Guid = Guid.Parse(guid); + } + + public Guid Guid { get; private set; } +} diff --git a/Voile.Common/Logging/IVoileLogSink.cs b/Voile.Common/Logging/IVoileLogSink.cs new file mode 100644 index 0000000..e79d790 --- /dev/null +++ b/Voile.Common/Logging/IVoileLogSink.cs @@ -0,0 +1,6 @@ +namespace Voile.Common.Logging; + +public interface IVoileLogSink +{ + void OnLogMessage(VoileLogMessage message); +} diff --git a/Voile.Common/Logging/Sinks/VoileConsoleSink.cs b/Voile.Common/Logging/Sinks/VoileConsoleSink.cs new file mode 100644 index 0000000..41da6fd --- /dev/null +++ b/Voile.Common/Logging/Sinks/VoileConsoleSink.cs @@ -0,0 +1,23 @@ +namespace Voile.Common.Logging.Sinks; + +public class VoileConsoleSink : IVoileLogSink +{ + private static VoileConsoleSink _instance; + + public static VoileConsoleSink GetInstance() + { + if (_instance == null) + { + _instance = new VoileConsoleSink(); + } + return _instance; + } + + private VoileConsoleSink() + {} + + public void OnLogMessage(VoileLogMessage message) + { + Console.WriteLine(String.Format("{0} {1} {2} - {3}", message.Timestamp.ToString(), message.Level.ToString(), message.SourceName, message.Message)); + } +} diff --git a/Voile.Common/Logging/VoileLogLevel.cs b/Voile.Common/Logging/VoileLogLevel.cs new file mode 100644 index 0000000..e7804ab --- /dev/null +++ b/Voile.Common/Logging/VoileLogLevel.cs @@ -0,0 +1,13 @@ +namespace Voile.Common.Logging; + +public enum VoileLogLevel : int +{ + OFF = 0, + FATAL = 100, + ERROR = 200, + WARN = 300, + INFO = 400, + DEBUG = 500, + TRACE = 600, + ALL = Int32.MaxValue +} diff --git a/Voile.Common/Logging/VoileLogManager.cs b/Voile.Common/Logging/VoileLogManager.cs new file mode 100644 index 0000000..5b15c5d --- /dev/null +++ b/Voile.Common/Logging/VoileLogManager.cs @@ -0,0 +1,67 @@ +namespace Voile.Common.Logging; + +public class VoileLogManager +{ + private VoileLogManager() + { + } + + private static VoileLogManager instance; + public static VoileLogManager GetInstance() + { + if (instance == null) + { + instance = new VoileLogManager(); + } + return instance; + } + + private List _sinks; + private Dictionary _producers; + + public void AddSink(IVoileLogSink sink) + { + if (_sinks == null) + _sinks = new List(); + _sinks.Add(sink); + } + + public void RemoveSink(IVoileLogSink sink) + { + if (_sinks == null) + return; + else + _sinks.Remove(sink); + } + + public static VoileLogger GetLogger(Type type) + { + return GetLogger(type.Name); + } + + public static VoileLogger GetLogger(string name) + { + VoileLogManager instance = GetInstance(); + + if (instance._producers == null) + instance._producers = new Dictionary(); + + if (instance._producers.ContainsKey(name)) + return instance._producers[name]; + + VoileLogger child = new VoileLogger(name, instance); + instance._producers.Add(name, child); + return child; + } + + internal void ProcessMessage(VoileLogMessage produced) + { + if (_sinks == null) + return; + + foreach (IVoileLogSink sink in _sinks) + { + sink.OnLogMessage(produced); + } + } +} diff --git a/Voile.Common/Logging/VoileLogMessage.cs b/Voile.Common/Logging/VoileLogMessage.cs new file mode 100644 index 0000000..3630ac9 --- /dev/null +++ b/Voile.Common/Logging/VoileLogMessage.cs @@ -0,0 +1,17 @@ +namespace Voile.Common.Logging; + +public class VoileLogMessage +{ + public VoileLogMessage(DateTime timestamp, VoileLogLevel level, string sourceName, string message) + { + Timestamp = timestamp; + Level = level; + SourceName = sourceName; + Message = message; + } + + public DateTime Timestamp { get; private set; } + public VoileLogLevel Level { get; private set; } + public string SourceName { get; private set; } + public string Message { get; private set; } +} diff --git a/Voile.Common/Logging/VoileLogger.cs b/Voile.Common/Logging/VoileLogger.cs new file mode 100644 index 0000000..f158378 --- /dev/null +++ b/Voile.Common/Logging/VoileLogger.cs @@ -0,0 +1,39 @@ +namespace Voile.Common.Logging; + +public class VoileLogger +{ + private readonly string _name; + private readonly VoileLogManager _manager; + + internal VoileLogger(string name, VoileLogManager manager) + { + _name = name; + _manager = manager; + } + + public void Log(VoileLogLevel level, string message) + { + VoileLogMessage produced = new VoileLogMessage(DateTime.Now, level, _name, message); + _manager.ProcessMessage(produced); + } + + public void Info(string message, params object[] args) + { + Log(VoileLogLevel.INFO, String.Format(message, args)); + } + + public void Warn(string message, params object[] args) + { + Log(VoileLogLevel.WARN, String.Format(message, args)); + } + + public void Error(string message, params object[] args) + { + Log(VoileLogLevel.ERROR, String.Format(message, args)); + } + + public void Debug(string message, params object[] args) + { + Log(VoileLogLevel.DEBUG, String.Format(message, args)); + } +} diff --git a/Voile.Common/Reflection/AutoconfigurableAttribute.cs b/Voile.Common/Reflection/AutoconfigurableAttribute.cs new file mode 100644 index 0000000..6aef924 --- /dev/null +++ b/Voile.Common/Reflection/AutoconfigurableAttribute.cs @@ -0,0 +1,12 @@ +namespace Voile.Common.Reflection; + +[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)] +public sealed class AutoconfigurableAttribute : Attribute +{ + // See the attribute guidelines at + // http://go.microsoft.com/fwlink/?LinkId=85236 + public AutoconfigurableAttribute() + { + + } +} diff --git a/Voile.Common/Reflection/Autoconfigurer.cs b/Voile.Common/Reflection/Autoconfigurer.cs new file mode 100644 index 0000000..efb767c --- /dev/null +++ b/Voile.Common/Reflection/Autoconfigurer.cs @@ -0,0 +1,56 @@ +using System.Reflection; +using Voile.Common.Configuration; +using Voile.Common.Logging; + +namespace Voile.Common.Reflection; + +public class Autoconfigurer +{ + private static Autoconfigurer instance; + private static VoileLogger logger = VoileLogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); + private Autoconfigurer() + { + } + + public static Autoconfigurer GetInstance() + { + if (instance == null) + { + instance = new Autoconfigurer(); + } + return instance; + } + + public void Autoconfigure(IConfigurationSource source, string categoryName, object target) + { + Type type = target.GetType(); + PropertyInfo[] propertyInfos = type.GetProperties(); + + foreach (PropertyInfo propertyInfo in propertyInfos) + { + AutoconfigurableAttribute? autoconfigurableAttribute = propertyInfo.GetCustomAttribute(); + if (autoconfigurableAttribute == null) + continue; + + Type propertyInfoPropertyType = propertyInfo.PropertyType; + switch (propertyInfoPropertyType.Name) + { + case "Boolean": + bool booleanValue = source.ReadValue(categoryName, propertyInfo.Name, false); + propertyInfo.SetValue(target, booleanValue, null); + break; + case "Int32": + int intValue = source.ReadValue(categoryName, propertyInfo.Name, 0); + propertyInfo.SetValue(target, intValue, null); + break; + case "String": + string stringValue = source.ReadValue(categoryName, propertyInfo.Name, string.Empty); + propertyInfo.SetValue(target, stringValue, null); + break; + default: + logger.Error("Don't know how to autoconfigure an {0}.", propertyInfoPropertyType.Name); + continue; + } + } + } +} diff --git a/Voile.Common/Reflection/IncompleteAttribute.cs b/Voile.Common/Reflection/IncompleteAttribute.cs new file mode 100644 index 0000000..0f08dcf --- /dev/null +++ b/Voile.Common/Reflection/IncompleteAttribute.cs @@ -0,0 +1,10 @@ +namespace Voile.Common.Reflection; + +[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)] +public sealed class IncompleteAttribute : Attribute +{ + public IncompleteAttribute() + { + + } +} diff --git a/Voile.Common/Reflection/VoilePluginAttribute.cs b/Voile.Common/Reflection/VoilePluginAttribute.cs new file mode 100644 index 0000000..f3306bc --- /dev/null +++ b/Voile.Common/Reflection/VoilePluginAttribute.cs @@ -0,0 +1,10 @@ +namespace Voile.Common.Reflection; + +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +public sealed class VoilePluginAttribute : Attribute +{ + public VoilePluginAttribute() + { + + } +} diff --git a/Voile.Common/VoileException.cs b/Voile.Common/VoileException.cs new file mode 100644 index 0000000..a721f17 --- /dev/null +++ b/Voile.Common/VoileException.cs @@ -0,0 +1,16 @@ +namespace Voile.Common; + +public class VoileException : Exception +{ + public VoileException() + { + } + + public VoileException(string message) : base(message) + { + } + + public VoileException(string message, Exception inner) : base(message, inner) + { + } +} diff --git a/Voile.Storage.Oracle/Voile.Storage.Oracle.csproj b/Voile.Storage.Oracle/Voile.Storage.Oracle.csproj index fa71b7a..7d52b5f 100644 --- a/Voile.Storage.Oracle/Voile.Storage.Oracle.csproj +++ b/Voile.Storage.Oracle/Voile.Storage.Oracle.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/Voile.Storage.Postgresql/Voile.Storage.Postgresql.csproj b/Voile.Storage.Postgresql/Voile.Storage.Postgresql.csproj index fa71b7a..7d52b5f 100644 --- a/Voile.Storage.Postgresql/Voile.Storage.Postgresql.csproj +++ b/Voile.Storage.Postgresql/Voile.Storage.Postgresql.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/Voile.Storage.SqlServer/Voile.Storage.SqlServer.csproj b/Voile.Storage.SqlServer/Voile.Storage.SqlServer.csproj index fa71b7a..7d52b5f 100644 --- a/Voile.Storage.SqlServer/Voile.Storage.SqlServer.csproj +++ b/Voile.Storage.SqlServer/Voile.Storage.SqlServer.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/Voile.slnx b/Voile.slnx index f6192fa..3cf0ff0 100644 --- a/Voile.slnx +++ b/Voile.slnx @@ -1,8 +1,10 @@ - - - + + + + +