From b74eb5b958ab341b30531bc955d3692258867671 Mon Sep 17 00:00:00 2001 From: Andreas Mueller Date: Sun, 24 Oct 2021 16:51:17 +0200 Subject: [PATCH] =?UTF-8?q?Kleinere=20=C3=84nderungen,=20Dokumentation=20u?= =?UTF-8?q?nd=20Git-Dateien?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AMWD.Common.AspNetCore.csproj | 5 +- .../ApplicationBuilderExtensions.cs | 5 +- .../ModelStateDictionaryExtensions.cs | 2 - ...s => InvariantFloatingPointModelBinder.cs} | 8 +- ...ariantFloatingPointModelBinderProvider.cs} | 4 +- .../AMWD.Common.EntityFrameworkCore.csproj | 5 +- AMWD.Common/AMWD.Common.csproj | 5 +- AMWD.Common/Utilities/DelayedTask.cs | 147 ++++++------------ AMWD.Common/Utilities/NetworkHelper.cs | 126 +++++++++------ Common.sln | 9 +- LICENSE.txt | 21 +++ README.md | 20 +++ 12 files changed, 187 insertions(+), 170 deletions(-) rename AMWD.Common.AspNetCore/ModelBinders/{CustomFloatingPointModelBinder.cs => InvariantFloatingPointModelBinder.cs} (88%) rename AMWD.Common.AspNetCore/ModelBinders/{CustomFloatingPointModelBinderProvider.cs => InvariantFloatingPointModelBinderProvider.cs} (89%) create mode 100644 LICENSE.txt create mode 100644 README.md diff --git a/AMWD.Common.AspNetCore/AMWD.Common.AspNetCore.csproj b/AMWD.Common.AspNetCore/AMWD.Common.AspNetCore.csproj index fb2fb64..90ea471 100644 --- a/AMWD.Common.AspNetCore/AMWD.Common.AspNetCore.csproj +++ b/AMWD.Common.AspNetCore/AMWD.Common.AspNetCore.csproj @@ -19,7 +19,10 @@ AMWD.Common.AspNetCore icon.png - https://git.am-wd.de/AM.WD/common + https://wiki.am-wd.de/libs/common + + git + https://git.am-wd.de/AM.WD/common.git AM.WD Common Library for ASP.NET Core Library with classes and extensions used frequently on AM.WD projects. diff --git a/AMWD.Common.AspNetCore/Extensions/ApplicationBuilderExtensions.cs b/AMWD.Common.AspNetCore/Extensions/ApplicationBuilderExtensions.cs index 356080e..334ed04 100644 --- a/AMWD.Common.AspNetCore/Extensions/ApplicationBuilderExtensions.cs +++ b/AMWD.Common.AspNetCore/Extensions/ApplicationBuilderExtensions.cs @@ -14,9 +14,8 @@ namespace Microsoft.AspNetCore.Builder /// Adds settings to run behind a reverse proxy (e.g. NginX). /// /// - /// A base path (e.g. running in a sub-directory /app) for the application is defined via
- /// - ASPNETCORE_APPL_PATH environment variable (preferred)
- /// - AspNetCore_Appl_Path in the settings file
+ /// A base path (e.g. running in a sub-directory /app) for the application is defined via ASPNETCORE_APPL_PATH environment variable. + ///
///
/// Additionally you can specify the proxy server by using or a when there are multiple proxy servers. ///
diff --git a/AMWD.Common.AspNetCore/Extensions/ModelStateDictionaryExtensions.cs b/AMWD.Common.AspNetCore/Extensions/ModelStateDictionaryExtensions.cs index c7c3c97..d539746 100644 --- a/AMWD.Common.AspNetCore/Extensions/ModelStateDictionaryExtensions.cs +++ b/AMWD.Common.AspNetCore/Extensions/ModelStateDictionaryExtensions.cs @@ -19,9 +19,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// The that specifies the property. /// The error message to add. /// No member expression provided. -#pragma warning disable IDE0060 // remove unused parameters public static void AddModelError(this ModelStateDictionary modelState, TModel model, Expression> keyExpression, string errorMessage) -#pragma warning restore IDE0060 // remove unused parameters { if (modelState is null) throw new ArgumentNullException(nameof(modelState)); diff --git a/AMWD.Common.AspNetCore/ModelBinders/CustomFloatingPointModelBinder.cs b/AMWD.Common.AspNetCore/ModelBinders/InvariantFloatingPointModelBinder.cs similarity index 88% rename from AMWD.Common.AspNetCore/ModelBinders/CustomFloatingPointModelBinder.cs rename to AMWD.Common.AspNetCore/ModelBinders/InvariantFloatingPointModelBinder.cs index 0ce5e52..706d792 100644 --- a/AMWD.Common.AspNetCore/ModelBinders/CustomFloatingPointModelBinder.cs +++ b/AMWD.Common.AspNetCore/ModelBinders/InvariantFloatingPointModelBinder.cs @@ -9,24 +9,24 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Custom floating point ModelBinder as the team of Microsoft is not capable of fixing their issue with other cultures than en-US. /// - public class CustomFloatingPointModelBinder : IModelBinder + public class InvariantFloatingPointModelBinder : IModelBinder { private readonly NumberStyles supportedNumberStyles; private readonly ILogger logger; private readonly CultureInfo cultureInfo; /// - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// The . /// The . /// The . - public CustomFloatingPointModelBinder(NumberStyles supportedStyles, CultureInfo cultureInfo, ILoggerFactory loggerFactory) + public InvariantFloatingPointModelBinder(NumberStyles supportedStyles, CultureInfo cultureInfo, ILoggerFactory loggerFactory) { this.cultureInfo = cultureInfo ?? throw new ArgumentNullException(nameof(cultureInfo)); supportedNumberStyles = supportedStyles; - logger = loggerFactory?.CreateLogger(); + logger = loggerFactory?.CreateLogger(); } /// diff --git a/AMWD.Common.AspNetCore/ModelBinders/CustomFloatingPointModelBinderProvider.cs b/AMWD.Common.AspNetCore/ModelBinders/InvariantFloatingPointModelBinderProvider.cs similarity index 89% rename from AMWD.Common.AspNetCore/ModelBinders/CustomFloatingPointModelBinderProvider.cs rename to AMWD.Common.AspNetCore/ModelBinders/InvariantFloatingPointModelBinderProvider.cs index fcaa809..cb61ed5 100644 --- a/AMWD.Common.AspNetCore/ModelBinders/CustomFloatingPointModelBinderProvider.cs +++ b/AMWD.Common.AspNetCore/ModelBinders/InvariantFloatingPointModelBinderProvider.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// options.ModelBinderProviders.Insert(0, new CustomFloatingPointModelBinderProvider());
/// }); ///
- public class CustomFloatingPointModelBinderProvider : IModelBinderProvider + public class InvariantFloatingPointModelBinderProvider : IModelBinderProvider { /// /// Gets or sets the supported globally. @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding modelType == typeof(double) || modelType == typeof(float)) { - return new CustomFloatingPointModelBinder(SupportedNumberStyles, CultureInfo, loggerFactory); + return new InvariantFloatingPointModelBinder(SupportedNumberStyles, CultureInfo, loggerFactory); } return null; diff --git a/AMWD.Common.EntityFrameworkCore/AMWD.Common.EntityFrameworkCore.csproj b/AMWD.Common.EntityFrameworkCore/AMWD.Common.EntityFrameworkCore.csproj index cc2685f..6c306ec 100644 --- a/AMWD.Common.EntityFrameworkCore/AMWD.Common.EntityFrameworkCore.csproj +++ b/AMWD.Common.EntityFrameworkCore/AMWD.Common.EntityFrameworkCore.csproj @@ -19,7 +19,10 @@ AMWD.Common.EntityFrameworkCore icon.png - https://git.am-wd.de/AM.WD/common + https://wiki.am-wd.de/libs/common + + git + https://git.am-wd.de/AM.WD/common.git AM.WD Common Library for EntityFramework Core Library with classes and extensions used frequently on AM.WD projects. diff --git a/AMWD.Common/AMWD.Common.csproj b/AMWD.Common/AMWD.Common.csproj index 0c00c3c..554f691 100644 --- a/AMWD.Common/AMWD.Common.csproj +++ b/AMWD.Common/AMWD.Common.csproj @@ -19,7 +19,10 @@ AMWD.Common icon.png - https://git.am-wd.de/AM.WD/common + https://wiki.am-wd.de/libs/common + + git + https://git.am-wd.de/AM.WD/common.git AM.WD Common Library Library with classes and extensions used frequently on AM.WD projects. diff --git a/AMWD.Common/Utilities/DelayedTask.cs b/AMWD.Common/Utilities/DelayedTask.cs index a4b68aa..8d20124 100644 --- a/AMWD.Common/Utilities/DelayedTask.cs +++ b/AMWD.Common/Utilities/DelayedTask.cs @@ -5,16 +5,20 @@ using System.Threading.Tasks; namespace AMWD.Common.Utilities { + // originally inspired by a code from Yves Goergen (unclassified.software). + /// - /// Implements an awaitable task that runs after a specified delay. The delay can be reset - /// before and after the task has run. By resetting the delay, the task can be executed multiple - /// times. The scheduled or executing or last executed task can be awaited, until the delay is - /// reset. After that, the next execution can be awaited. + /// Implements an awaitable task that runs after a specified delay. The delay can be reset. + /// By resetting the delay, the task can be executed multiple times. /// public class DelayedTask { #region Data + private Timer timer; + + private bool nextRunPending; + /// /// The synchronisation object. /// @@ -25,7 +29,15 @@ namespace AMWD.Common.Utilities /// protected Action exceptionHandler; - private Timer timer; + /// + /// Provides the for the method. + /// + protected TaskCompletionSourceWrapper tcs; + + /// + /// Gets or sets the action to execute. + /// + protected Action Action { get; set; } /// /// Gets a value indicating whether the timer is running and an execution is scheduled. This @@ -39,22 +51,6 @@ namespace AMWD.Common.Utilities /// public bool IsRunning { get; private set; } - /// - /// Indicates whether the action shall be executed again after the currently ongoing - /// execution has completed. - /// - private bool nextRunPending; - - /// - /// Provides the for the method. - /// - protected TaskCompletionSourceWrapper tcs; - - /// - /// Gets or sets the action to execute. - /// - protected Action Action { get; set; } - /// /// Gets or sets the delay to wait before executing the action. /// @@ -66,53 +62,41 @@ namespace AMWD.Common.Utilities /// /// Creates a new task instance that executes the specified action after the delay, but does - /// not start it yet. Multiple executions are allowed when calling after - /// the executed was started. + /// not start it yet. /// /// The action to execute. /// The delay. /// public static DelayedTask Create(Action action, TimeSpan delay) - { - return new DelayedTask { Action = action, Delay = delay }; - } + => new() { Action = action, Delay = delay }; /// /// Creates a new task instance that executes the specified action after the delay, but does - /// not start it yet. Multiple executions are allowed when calling after - /// the executed was started. + /// not start it yet. /// /// The action to execute. /// The delay. /// public static DelayedTaskWithResult Create(Func action, TimeSpan delay) - { - return DelayedTaskWithResult.Create(action, delay); - } + => DelayedTaskWithResult.Create(action, delay); /// - /// Executes the specified action after the delay. Multiple executions are allowed when - /// calling after the executed was started. + /// Executes the specified action after the delay. /// /// The action to execute. /// The delay. /// public static DelayedTask Run(Action action, TimeSpan delay) - { - return new DelayedTask { Action = action, Delay = delay }.Start(); - } + => new DelayedTask { Action = action, Delay = delay }.Start(); /// - /// Executes the specified action after the delay. Multiple executions are allowed when - /// calling after the executed was started. + /// Executes the specified action after the delay. /// /// The action to execute. /// The delay. /// public static DelayedTaskWithResult Run(Func action, TimeSpan delay) - { - return DelayedTaskWithResult.Run(action, delay); - } + => DelayedTaskWithResult.Run(action, delay); #endregion Static methods @@ -158,7 +142,7 @@ namespace AMWD.Common.Utilities } /// - /// Cancels the delay. Any pending executions are cleared. If the action was pending but not + /// Cancels the delay. Any pending execution is cleared. If the action was pending but not /// yet executing, this task is cancelled. If the action was not pending or is already /// executing, this task will be completed successfully after the action has completed. /// @@ -185,13 +169,7 @@ namespace AMWD.Common.Utilities /// /// Starts a pending execution immediately, not waiting for the timer to elapse. /// - /// true, if an execution was started; otherwise, false. - /// - /// A new execution is only started if one is currently waiting to run, or already running. - /// In the former case, the execution is scheduled immediately with the timer; in the latter - /// case, it is scheduled for when the currently running execution has completed. If an - /// execution has been started (the method returned true), it can be awaited normally. - /// + /// true, if an execution was started; otherwise, false. public bool ExecutePending() { lock (syncObj) @@ -287,9 +265,7 @@ namespace AMWD.Common.Utilities /// /// protected virtual TaskCompletionSourceWrapper CreateTcs() - { - return new TaskCompletionSourceWrapper(); - } + => new TaskCompletionSourceWrapper(); /// /// Called when the timer has elapsed. @@ -366,18 +342,19 @@ namespace AMWD.Common.Utilities // Unblock waiters if not already waiting for the next execution. // This task can be awaited again after the Reset method has been called. if (exception != null) + { localTcs?.TrySetException(exception); + } else + { SetLastResult(localTcs); + } } /// /// Runs the action of the task. /// - protected virtual void Run() - { - Action(); - } + protected virtual void Run() => Action(); /// /// Sets the result from the last action. @@ -447,31 +424,13 @@ namespace AMWD.Common.Utilities /// /// The result value to bind to this . /// - public void TrySetResult(TResult result) - { - tcs.TrySetResult(result); - } + public void TrySetResult(TResult result) => tcs.TrySetResult(result); - /// - /// Attempts to transition the underlying into the - /// state and binds it to a specified exception. - /// - /// The exception to bind to this . - /// - public override void TrySetException(Exception exception) - { - tcs.TrySetException(exception); - } + /// + public override void TrySetException(Exception exception) => tcs.TrySetException(exception); - /// - /// Attempts to transition the underlying into the - /// state. - /// - /// - public override void TrySetCanceled() - { - tcs.TrySetCanceled(); - } + /// + public override void TrySetCanceled() => tcs.TrySetCanceled(); } #endregion Internal TaskCompletionSourceWrapper classes @@ -497,36 +456,22 @@ namespace AMWD.Common.Utilities protected new Func Action { get; set; } internal static DelayedTaskWithResult Create(Func action, TimeSpan delay) - { - return new DelayedTaskWithResult { Action = action, Delay = delay }; - } + => new() { Action = action, Delay = delay }; internal static DelayedTaskWithResult Run(Func action, TimeSpan delay) - { - return (DelayedTaskWithResult)new DelayedTaskWithResult { Action = action, Delay = delay }.Start(); - } + => (DelayedTaskWithResult)new DelayedTaskWithResult { Action = action, Delay = delay }.Start(); - /// - /// Creates a instance. - /// - /// + /// protected override TaskCompletionSourceWrapper CreateTcs() - { - return new TaskCompletionSourceWrapper(); - } + => new TaskCompletionSourceWrapper(); - /// - /// Runs the action of the task. - /// + /// protected override void Run() { lastResult = Action(); } - /// - /// Sets the result from the last action. - /// - /// The to set the result of. + /// protected override void SetLastResult(TaskCompletionSourceWrapper tcs) { var myTcs = (TaskCompletionSourceWrapper)tcs; @@ -570,9 +515,7 @@ namespace AMWD.Common.Utilities /// The instance to cast. /// A that represents the current awaitable operation. public static implicit operator Task(DelayedTaskWithResult delayedTask) - { - return delayedTask.Task; - } + => delayedTask.Task; /// /// Adds an unhandled exception handler to this instance. diff --git a/AMWD.Common/Utilities/NetworkHelper.cs b/AMWD.Common/Utilities/NetworkHelper.cs index edab132..f69df64 100644 --- a/AMWD.Common/Utilities/NetworkHelper.cs +++ b/AMWD.Common/Utilities/NetworkHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.NetworkInformation; @@ -12,70 +13,93 @@ namespace AMWD.Common.Utilities public static class NetworkHelper { /// - /// Tries to resolve a into an to connect to. + /// Tries to resolve a to its es. /// /// The hostname to resolve. /// An address family to use (available: and ). - /// The fallback ip address when resolving failed. - /// The resolved to connect to or value. - public static IPAddress ResolveHost(string hostname, AddressFamily addressFamily = AddressFamily.Unspecified, IPAddress fallback = null) + /// The resolved es or an empty list. + public static List ResolveHost(string hostname, AddressFamily addressFamily = default) { - if (IPAddress.TryParse(hostname, out var ipAddress)) - { - if (ipAddress.AddressFamily != AddressFamily.InterNetwork && ipAddress.AddressFamily != AddressFamily.InterNetworkV6) - return fallback; + if (string.IsNullOrWhiteSpace(hostname)) + return new(); - if (addressFamily != AddressFamily.Unspecified && ipAddress.AddressFamily != addressFamily) - return fallback; + if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) + addressFamily = AddressFamily.Unspecified; - return ipAddress; - } - - return Dns.GetHostAddresses(hostname) - .Where(a => a.AddressFamily == AddressFamily.InterNetwork || a.AddressFamily == AddressFamily.InterNetworkV6) - .Where(a => addressFamily == AddressFamily.Unspecified || a.AddressFamily == addressFamily) - .OrderBy(a => a.AddressFamily) - .FirstOrDefault() ?? fallback; - } - - /// - /// Tries to resolve a into an to bind (listen) on. - /// - /// The interface name to resolve. - /// An address family to use (available: and ). - /// The fallback ip address when resolving failed. - /// The resolved to bind on or value. - public static IPAddress ResolveInterface(string iface, AddressFamily addressFamily = AddressFamily.Unspecified, IPAddress fallback = null) - { - if (IPAddress.TryParse(iface, out var ipAddress)) - { - if (ipAddress.AddressFamily != AddressFamily.InterNetwork && ipAddress.AddressFamily != AddressFamily.InterNetworkV6) - return fallback; - - if (addressFamily != AddressFamily.Unspecified && ipAddress.AddressFamily != addressFamily) - return fallback; - - return ipAddress; - } + var ipAddress = ResolveIpAddress(hostname, addressFamily); + // the name was an ip address, should not happen but experience tells other stories + if (ipAddress != null) + return new() { ipAddress }; try { - return Dns.GetHostAddresses(iface) - .Where(a => a.AddressFamily == AddressFamily.InterNetwork || a.AddressFamily == AddressFamily.InterNetworkV6) - .Where(a => addressFamily == AddressFamily.Unspecified || a.AddressFamily == addressFamily) - .OrderBy(a => a.AddressFamily) - .FirstOrDefault() ?? fallback; + return Dns.GetHostAddresses(hostname) + .FilterAddressFamily(addressFamily) + .ToList(); } - catch (SocketException) + catch + { + return new(); + } + } + + /// + /// Tries to resolve an interface name to its v4 and v6 es. + /// + /// The interface name to resolve. + /// An address family to use (available: and ). + /// The resolved es or an empty list. + public static List ResolveInterface(string interfaceName, AddressFamily addressFamily = default) + { + if (string.IsNullOrWhiteSpace(interfaceName)) + return new(); + + if (addressFamily != AddressFamily.InterNetwork && addressFamily != AddressFamily.InterNetworkV6) + addressFamily = AddressFamily.Unspecified; + + var ipAddress = ResolveIpAddress(interfaceName, addressFamily); + // the name was an ip address, should not happen but experience tells other stories + if (ipAddress != null) + return new() { ipAddress }; + + try { return NetworkInterface.GetAllNetworkInterfaces() - .Where(nic => nic.Name.Equals(iface, StringComparison.OrdinalIgnoreCase)) - .SelectMany(nic => nic.GetIPProperties().UnicastAddresses.Select(ai => ai.Address)) - .Where(a => a.AddressFamily == AddressFamily.InterNetwork || a.AddressFamily == AddressFamily.InterNetworkV6) - .Where(a => addressFamily == AddressFamily.Unspecified || a.AddressFamily == addressFamily) - .OrderBy(a => a.AddressFamily) - .FirstOrDefault() ?? fallback; + .Where(nic => nic.Name.Equals(interfaceName, StringComparison.OrdinalIgnoreCase)) + .SelectMany(nic => nic.GetIPProperties().UnicastAddresses.Select(uai => uai.Address)) + .FilterAddressFamily(addressFamily) + .ToList(); } + catch + { + return new(); + } + } + + private static IPAddress ResolveIpAddress(string address, AddressFamily addressFamily) + { + if (IPAddress.TryParse(address, out var ipAddress)) + { + // the address is whether IPv4 nor IPv6 + if (ipAddress.AddressFamily != AddressFamily.InterNetwork && ipAddress.AddressFamily != AddressFamily.InterNetworkV6) + return null; + + // the address does not match the required address family + if (addressFamily != AddressFamily.Unspecified && ipAddress.AddressFamily != addressFamily) + return null; + + return ipAddress; + } + + return null; + } + + private static IEnumerable FilterAddressFamily(this IEnumerable source, AddressFamily addressFamily) + { + return source + .Where(a => a.AddressFamily == AddressFamily.InterNetwork || a.AddressFamily == AddressFamily.InterNetworkV6) + .Where(a => addressFamily == AddressFamily.Unspecified || a.AddressFamily == addressFamily) + .OrderBy(a => a.AddressFamily); } } } diff --git a/Common.sln b/Common.sln index b9a880d..24ea6f4 100644 --- a/Common.sln +++ b/Common.sln @@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.31729.503 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AMWD.Common", "AMWD.Common\AMWD.Common.csproj", "{F512C474-B670-4E47-911E-7C0674AA8E7E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AMWD.Common", "AMWD.Common\AMWD.Common.csproj", "{F512C474-B670-4E47-911E-7C0674AA8E7E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AMWD.Common.AspNetCore", "AMWD.Common.AspNetCore\AMWD.Common.AspNetCore.csproj", "{725F40C9-8172-487F-B3D0-D7E38B4DB197}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AMWD.Common.AspNetCore", "AMWD.Common.AspNetCore\AMWD.Common.AspNetCore.csproj", "{725F40C9-8172-487F-B3D0-D7E38B4DB197}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AMWD.Common.EntityFrameworkCore", "AMWD.Common.EntityFrameworkCore\AMWD.Common.EntityFrameworkCore.csproj", "{7091CECF-C981-4FB9-9CC6-91C4E65A6356}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AMWD.Common.EntityFrameworkCore", "AMWD.Common.EntityFrameworkCore\AMWD.Common.EntityFrameworkCore.csproj", "{7091CECF-C981-4FB9-9CC6-91C4E65A6356}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AFBF83AE-FE7D-48C1-B7E7-31BF3E17C6FB}" ProjectSection(SolutionItems) = preProject @@ -15,6 +15,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .gitignore = .gitignore .gitlab-ci.yml = .gitlab-ci.yml CodeMaid.config = CodeMaid.config + icon.png = icon.png + LICENSE.txt = LICENSE.txt + README.md = README.md EndProjectSection EndProject Global diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..c6a64eb --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2020-2021 Andreas Müller + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6762e80 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Common + +This is a collection of commonly used extensions, etc. on my projects. +To save time, they are all packed to NuGet packages. + +## Documentation + +Documentation can be found here: [AM.WD Wiki](https://wiki.am-wd.de/libs/common) + +## Use in projects + +Create a `nuget.config` file in your root project folder (where the `.sln` file is located) +``` + + + + + + +```