Compare commits

...

4 Commits

Author SHA1 Message Date
Matthias Heil 90bca23d53 removed other projects 2026-04-05 10:34:49 +02:00
Matthias Heil 149de07b0e Removed CommonCore 2026-04-05 08:18:25 +02:00
Matthias Heil 511a5f9f51 Fixed Warnings 2026-04-05 08:00:09 +02:00
Matthias Heil dfb879bfb3 Added Directory.Build.props to avoid mixed app.settings 2026-04-05 07:33:29 +02:00
88 changed files with 153 additions and 1816 deletions
+2
View File
@@ -1 +1,3 @@
/.vs /.vs
/bin
/packages
@@ -1,16 +0,0 @@
<Application x:Class="AvaloniaLoggingDI.App"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AvaloniaLoggingDI">
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme/>
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
</Application.Styles>
</Application>
@@ -1,173 +0,0 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using AvaloniaLoggingDI.ViewModels;
using AvaloniaLoggingDI.Views;
using LogViewer.Avalonia;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MsBox.Avalonia;
using MsBox.Avalonia.Enums;
using MsLogger.Core;
using RandomLogging.Service;
using System;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Threading;
using Icon = MsBox.Avalonia.Enums.Icon;
namespace AvaloniaLoggingDI;
public partial class App : Application
{
public override void Initialize()
=> AvaloniaXamlLoader.Load(this);
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
DisableAvaloniaDataAnnotationValidation();
// catch all unhandled errors
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
HostApplicationBuilder builder = Host.CreateApplicationBuilder();
builder
/*
* Note: For information on launch profiles for debugging,
* see article: https://www.codeproject.com/Articles/5354478/NET-App-Settings-Demystified-Csharp-VB
*/
// Register the Random Logging Service
.AddRandomBackgroundService()
// visual debugging tools
.AddLogViewer()
// Microsoft Logger
//.Logging.AddDefaultDataStoreLogger();
// uncomment to use custom logging colors (note: System.Drawing namespace)
//
.Logging.AddDefaultDataStoreLogger(options =>
{
options.Colors[LogLevel.Trace] = new()
{
Foreground = Color.White,
Background = Color.DarkGray
};
options.Colors[LogLevel.Debug] = new()
{
Foreground = Color.White,
Background = Color.Gray
};
options.Colors[LogLevel.Information] = new()
{
Foreground = Color.White,
Background = Color.DodgerBlue
};
options.Colors[LogLevel.Warning] = new()
{
Foreground = Color.White,
Background = Color.Orchid
};
});
IServiceCollection services = builder.Services;
services
.AddSingleton<MainViewModel>()
.AddSingleton<MainWindow>(service => new MainWindow
{
DataContext = service.GetRequiredService<MainViewModel>()
});
_host = builder.Build();
_cancellationTokenSource = new();
try
{
LogStartingMode();
// set and show
desktop.MainWindow = _host.Services.GetRequiredService<MainWindow>();
desktop.ShutdownRequested += OnShutdownRequested;
// startup background services
_ = _host.StartAsync(_cancellationTokenSource.Token);
}
catch (OperationCanceledException)
{
// skip
}
catch (Exception ex)
{
ShowMessageBox("Unhandled Error", ex.Message);
return;
}
}
base.OnFrameworkInitializationCompleted();
}
private static void DisableAvaloniaDataAnnotationValidation()
{
// Get an array of plugins to remove
var dataValidationPluginsToRemove = BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
// remove each entry found
foreach (var plugin in dataValidationPluginsToRemove)
{
BindingPlugins.DataValidators.Remove(plugin);
}
}
private void OnShutdownRequested(object? sender, ShutdownRequestedEventArgs e)
=> _ = _host!.StopAsync(_cancellationTokenSource!.Token);
#region Fields
private IHost? _host;
private CancellationTokenSource? _cancellationTokenSource;
#endregion
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
=> ShowMessageBox("Unhandled Error", ((Exception)e.ExceptionObject).Message);
private static void ShowMessageBox(string title, string message)
{
var box = MessageBoxManager.GetMessageBoxStandard(
"Exception",
text: message,
ButtonEnum.Ok,
Icon.Stop
);
_ = box.ShowAsync().GetAwaiter();
}
private void LogStartingMode()
{
// Get the Launch mode
bool isDevelopment = string.Equals(Environment.GetEnvironmentVariable("DOTNET_MODIFIABLE_ASSEMBLIES"), "debug",
StringComparison.OrdinalIgnoreCase);
// initialize a logger & EventId
ILogger<App> logger = _host!.Services.GetRequiredService<ILogger<App>>();
EventId eventId = new EventId(id: 0, name: Assembly.GetEntryAssembly()!.GetName().Name);
// log a test pattern for each log level
logger.TestPattern(eventId: eventId);
// log that we have started...
logger.Emit(eventId, LogLevel.Information, $"Running in {(isDevelopment ? "Debug" : "Release")} mode");
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

@@ -1,41 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\avalonia-logo.ico" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="appsettings.Production.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<TrimmerRootAssembly Include="Avalonia.Themes.Fluent" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MessageBox.Avalonia" Version="3.3.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Background Services\RandomLogging.Service\RandomLogging.Service.csproj" />
<ProjectReference Include="..\..\Controls\LogViewer.Avalonia\LogViewer.Avalonia.csproj" />
<ProjectReference Include="..\..\Core\MsLogger.Core\MsLogger.Core.csproj" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\avalonia-logo.ico" />
</ItemGroup>
</Project>
@@ -1,21 +0,0 @@
using Avalonia;
using System;
namespace AvaloniaLoggingDI;
internal class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args)
=> BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.LogToTrace();
}
@@ -1,19 +0,0 @@
{
"profiles": {
"Development": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Staging": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Staging"
}
},
"Production": {
"commandName": "Project"
}
}
}
@@ -1,36 +0,0 @@
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using AvaloniaLoggingDI.ViewModels;
using System;
using System.Diagnostics.CodeAnalysis;
namespace AvaloniaLoggingDI;
// <summary>
/// Given a view model, returns the corresponding view if possible.
/// </summary>
[RequiresUnreferencedCode(
"Default implementation of ViewLocator involves reflection which may be trimmed away.",
Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")]
public class ViewLocator : IDataTemplate
{
public Control? Build(object? param)
{
if (param is null)
return null;
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}
@@ -1,21 +0,0 @@
using LogViewer.Core.ViewModels;
namespace AvaloniaLoggingDI.ViewModels;
public class MainViewModel : ViewModelBase
{
#region Constructor
public MainViewModel(LogViewerControlViewModel logViewer)
{
LogViewer = logViewer;
}
#endregion
#region Properties
public LogViewerControlViewModel LogViewer { get; }
#endregion
}
@@ -1,7 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace AvaloniaLoggingDI.ViewModels;
public class ViewModelBase : ObservableObject
{
}
@@ -1,19 +0,0 @@
<Window x:Class="AvaloniaLoggingDI.Views.MainWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Window"
xmlns:control="clr-namespace:LogViewer.Avalonia;assembly=LogViewer.Avalonia"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Title="C# AVALONIA | LogViewer Control Example - Dot Net 7.0"
Icon="/Assets/avalonia-logo.ico"
WindowStartupLocation="CenterScreen" Height="634" Width="600">
<control:LogViewerControl DataContext="{Binding LogViewer}" />
</Window>
@@ -1,8 +0,0 @@
using Avalonia.Controls;
namespace AvaloniaLoggingDI.Views;
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
}
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embeded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="AvaloniaTest.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"System.Net.Http.HttpClient": "Trace"
}
}
}
@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"System.Net.Http.HttpClient": "Warning"
}
}
}
@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"System.Net.Http.HttpClient": "Information"
}
}
}
@@ -1,9 +0,0 @@
<Application x:Class="AvaloniaLoggingNoDI.App"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Styles>
<FluentTheme/>
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
</Application.Styles>
</Application>
@@ -1,42 +0,0 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using AvaloniaLoggingNoDI.Views;
using System.Linq;
namespace AvaloniaLoggingNoDI;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
DisableAvaloniaDataAnnotationValidation();
desktop.MainWindow = new MainWindow();
}
base.OnFrameworkInitializationCompleted();
}
private static void DisableAvaloniaDataAnnotationValidation()
{
// Get an array of plugins to remove
var dataValidationPluginsToRemove =
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
// remove each entry found
foreach (var plugin in dataValidationPluginsToRemove)
{
BindingPlugins.DataValidators.Remove(plugin);
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

@@ -1,44 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\avalonia-logo.ico" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\avalonia-logo.ico" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="appsettings.Production.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<TrimmerRootAssembly Include="Avalonia.Themes.Fluent" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Background Services\RandomLogging.Service\RandomLogging.Service.csproj" />
<ProjectReference Include="..\..\Controls\LogViewer.Avalonia\LogViewer.Avalonia.csproj" />
<ProjectReference Include="..\..\Core\Common.Core\Common.Core.csproj" />
<ProjectReference Include="..\..\Core\MsLogger.Core\MsLogger.Core.csproj" />
</ItemGroup>
</Project>
@@ -1,10 +0,0 @@
using LogViewer.Core;
using LogDataStore = LogViewer.Avalonia.Logging.LogDataStore;
namespace AvaloniaLoggingNoDI.DataStores;
// Application-wide shared instance of the LogDataStore logging entries
public static class MainControlsDataStore
{
public static ILogDataStore DataStore { get; } = new LogDataStore();
}
@@ -1,30 +0,0 @@
using System;
using LogViewer.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;
using MsLogger.Core;
using AvaloniaLoggingNoDI.DataStores;
namespace AvaloniaLoggingNoDI.Extensions;
public static class LoggerExtension
{
public static ILoggingBuilder AddDataStoreLogger(this ILoggingBuilder builder)
{
builder.AddConfiguration();
// We need to use a shared instance of the DataStore to pass to the LogViewerControl
builder.Services.AddSingleton(MainControlsDataStore.DataStore);
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, DataStoreLoggerProvider>());
return builder;
}
public static ILoggingBuilder AddDataStoreLogger(this ILoggingBuilder builder, Action<DataStoreLoggerConfiguration> configure)
{
builder.AddDataStoreLogger();
builder.Services.Configure(configure);
return builder;
}
}
@@ -1,78 +0,0 @@
using System;
using System.Drawing;
using Common.Core;
using Microsoft.Extensions.Logging;
using AvaloniaLoggingNoDI.Extensions;
namespace AvaloniaLoggingNoDI.Helpers;
// application-wide DataStoreLogger Factory ... returns a wired up Logger instance
public static class LoggingHelper
{
#region Constructors
static LoggingHelper()
{
// retrieve the log level from 'appsettings'
string value = AppSettings<string>.Current("Logging:LogLevel", "Default") ?? "Information";
Enum.TryParse(value, out LogLevel logLevel);
// wire up the loggers
Factory = LoggerFactory.Create(builder => builder
// visual debugging tools
//.AddDataStoreLogger()
// uncomment to use custom logging colors (note: System.Drawing namespace)
//
.AddDataStoreLogger(options =>
{
options.Colors[LogLevel.Trace] = new()
{
Foreground = Color.White,
Background = Color.DarkGray
};
options.Colors[LogLevel.Debug] = new()
{
Foreground = Color.White,
Background = Color.Gray
};
options.Colors[LogLevel.Information] = new()
{
Foreground = Color.White,
Background = Color.DodgerBlue
};
options.Colors[LogLevel.Warning] = new()
{
Foreground = Color.White,
Background = Color.Orchid
};
})
// examples of adding other loggers...
.AddSimpleConsole(options =>
{
options.SingleLine = true;
options.TimestampFormat = "hh:mm:ss ";
})
// note:
// * The IDE will automatically add the Debugger Logger, even though not visible
// * Adding the DebugLogger is useful for remote debugging
//.AddDebug()
// set minimum log level from 'appsettings'
.SetMinimumLevel(logLevel));
}
#endregion
#region Properties
public static ILoggerFactory Factory { get; }
#endregion
}
@@ -1,21 +0,0 @@
using Avalonia;
using System;
namespace AvaloniaLoggingNoDI;
internal class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args)
=> BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.LogToTrace();
}
@@ -1,19 +0,0 @@
{
"profiles": {
"Development": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Staging": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Staging"
}
},
"Production": {
"commandName": "Project"
}
}
}
@@ -1,19 +0,0 @@
<Window x:Class="AvaloniaLoggingNoDI.Views.MainWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Window"
xmlns:control="clr-namespace:LogViewer.Avalonia;assembly=LogViewer.Avalonia"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="C# AVALONIA MINIMAL | LogViewer Control Example - Dot Net 7.0"
Icon="/Assets/avalonia-logo.ico"
WindowStartupLocation="CenterScreen" Height="634" Width="600">
<control:LogViewerControl x:Name="LogViewerControl" />
</Window>
@@ -1,48 +0,0 @@
using Avalonia.Controls;
using AvaloniaLoggingNoDI.DataStores;
using AvaloniaLoggingNoDI.Helpers;
using LogViewer.Core;
using Microsoft.Extensions.Logging;
using RandomLogging.Service;
using System;
using System.Reflection;
using System.Threading;
namespace AvaloniaLoggingNoDI.Views;
public partial class MainWindow : Window, ILogDataStoreImpl
{
public MainWindow()
{
InitializeComponent();
// Initialize service and pass in the Logger
RandomLoggingService service = new(new Logger<RandomLoggingService>(LoggingHelper.Factory));
// Get the Launch mode
bool isDevelopment = string.Equals(Environment.GetEnvironmentVariable("DOTNET_MODIFIABLE_ASSEMBLIES"), "debug",
StringComparison.InvariantCultureIgnoreCase);
// initialize a logger & EventId
Logger<MainWindow> logger = new Logger<MainWindow>(LoggingHelper.Factory);
EventId eventId = new EventId(id: 0, name: Assembly.GetEntryAssembly()!.GetName().Name);
// log a test pattern for each log level
logger.TestPattern(eventId: eventId);
// log that we have started...
logger.Emit(eventId, LogLevel.Information, $"Running in {(isDevelopment ? "Debug" : "Release")} mode");
// Start generating log entries
_ = service.StartAsync(CancellationToken.None);
// manually wire up the logging to the view ... the control will show backlog entries...
DataStore = MainControlsDataStore.DataStore;
// we can't bind the controls' DataContext to a static object, so assign the DataStore to the Window
// and pass a reference to the Window itself
LogViewerControl.DataContext = this;
}
public ILogDataStore DataStore { get; init; }
}
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embeded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="AvaloniaTest.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"System.Net.Http.HttpClient": "Trace"
}
}
}
@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"System.Net.Http.HttpClient": "Warning"
}
}
}
@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"System.Net.Http.HttpClient": "Information"
}
}
}
@@ -1,14 +0,0 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AvaloniaSerilogDI"
x:Class="AvaloniaSerilogDI.App">
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
</Application.Styles>
</Application>
@@ -1,185 +0,0 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using AvaloniaSerilogDI.ViewModels;
using AvaloniaSerilogDI.Views;
using Common.Core.Extensions;
using LogViewer.Avalonia;
using LogViewer.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MsBox.Avalonia;
using MsBox.Avalonia.Enums;
using RandomLogging.Service;
using Serilog;
using Serilog.Sinks.LogView.Core;
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
using Icon = MsBox.Avalonia.Enums.Icon;
namespace AvaloniaSerilogDI;
public partial class App : Application
{
#region Constructors
public override void Initialize()
=> AvaloniaXamlLoader.Load(this);
#endregion
#region Fields
private IHost? _host;
private CancellationTokenSource? _cancellationTokenSource;
#endregion
#region Methods
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
DisableAvaloniaDataAnnotationValidation();
// catch all unhandled errors
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
HostApplicationBuilder builder = Host.CreateApplicationBuilder();
builder
// Register the Random Logging Service
.AddRandomBackgroundService()
// visual debugging tools
.AddLogViewer();
IServiceCollection services = builder.Services;
// Serilog Logger
// Azure: https://devblogs.microsoft.com/dotnet/asp-net-core-logging/
// ApplicationInsights: https://github.com/serilog-contrib/serilog-sinks-applicationinsights
// AmazonCloudWatch: https://blog.ivankahl.com/logging-dotnet-to-aws-cloudwatch-using-serilog/
// video: https://www.youtube.com/watch?v=nVAkSBpsuTk (How Structured Logging With Serilog Can Make Your Life Easier)
// video: https://www.youtube.com/watch?v=_iryZxv8Rxw (C# Logging with Serilog and Seq - Structured Logging Made Easy)
// ps: docker run -d --restart unless-stopped --name seq -e ACCEPT_EULA=Y -v c:\WIP\LogData:/data -p 8081:80 datalust/seq:latest
// docker rmi datalust/seq --force
// ref: https://stackoverflow.com/questions/66304596/how-to-dependency-inject-serilog-into-the-rest-of-my-classes-in-net-console-app
services.AddLogging(configure: cfg =>
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.WriteTo.DataStoreLoggerSink( dataStoreProvider: () => _host!.Services.TryGetService<ILogDataStore>()!,formatProvider: CultureInfo.InvariantCulture)
.CreateLogger();
cfg.ClearProviders().AddSerilog(Log.Logger);
});
services
.AddSingleton<MainViewModel>()
.AddSingleton(service => new MainWindow
{
DataContext = service.GetRequiredService<MainViewModel>()
});
_host = builder.Build();
_cancellationTokenSource = new();
try
{
LogStartingMode();
// set and show
desktop.MainWindow = _host.Services.GetRequiredService<MainWindow>();
desktop.ShutdownRequested += OnShutdownRequested;
// startup background services
_ = _host.StartAsync(_cancellationTokenSource.Token);
}
catch (OperationCanceledException)
{
// skip
}
catch (Exception ex)
{
Log.Fatal(ex, "Application terminated unexpectedly");
ShowMessageBox("Unhandled Error", ex.Message);
CleanUp();
return;
}
}
base.OnFrameworkInitializationCompleted();
}
private static void DisableAvaloniaDataAnnotationValidation()
{
// Get an array of plugins to remove
var dataValidationPluginsToRemove = BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
// remove each entry found
foreach (var plugin in dataValidationPluginsToRemove)
{
BindingPlugins.DataValidators.Remove(plugin);
}
}
private void OnShutdownRequested(object? sender, ShutdownRequestedEventArgs e)
=> CleanUp();
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception exception = (Exception)e.ExceptionObject;
Log.Fatal(exception, "Application terminated unexpectedly");
ShowMessageBox("Unhandled Error", exception.Message);
CleanUp();
}
private static void ShowMessageBox(string title, string message)
{
var box = MessageBoxManager.GetMessageBoxStandard(
"Exception",
text: message,
ButtonEnum.Ok,
Icon.Stop
);
_ = box.ShowAsync().GetAwaiter();
}
private void LogStartingMode()
{
// Get the Launch mode
bool isDevelopment = string.Equals(Environment.GetEnvironmentVariable("DOTNET_MODIFIABLE_ASSEMBLIES"), "debug",
StringComparison.OrdinalIgnoreCase);
// initialize a logger & EventId
ILogger<App> logger = _host!.Services.GetRequiredService<ILogger<App>>();
EventId eventId = new(id: 0, name: Assembly.GetEntryAssembly()!.GetName().Name);
// log a test pattern for each log level
logger.TestPattern(eventId: eventId);
// log that we have started...
logger.Emit(eventId, LogLevel.Information, $"Running in {(isDevelopment ? "Debug" : "Release")} mode");
}
private void CleanUp()
{
// tell the background services that we are shutting down
_ = _host?.StopAsync(_cancellationTokenSource?.Token ?? CancellationToken.None);
// flush logs
Log.CloseAndFlush();
}
#endregion
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

@@ -1,52 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\avalonia-logo.ico" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\avalonia-logo.ico" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="appsettings.Production.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<TrimmerRootAssembly Include="Avalonia.Themes.Fluent" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.5" />
<PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageReference Include="Serilog.Enrichers.Process" Version="3.0.0" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="10.0.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="10.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
<PackageReference Include="MessageBox.Avalonia" Version="3.3.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Background Services\RandomLogging.Service\RandomLogging.Service.csproj" />
<ProjectReference Include="..\..\Controls\LogViewer.Avalonia\LogViewer.Avalonia.csproj" />
<ProjectReference Include="..\..\Core\Common.Core\Common.Core.csproj" />
<ProjectReference Include="..\..\Core\Serilog.Sinks.LogView.Core\Serilog.Sinks.LogView.Core.csproj" />
</ItemGroup>
</Project>
@@ -1,20 +0,0 @@
using Avalonia;
using System;
namespace AvaloniaSerilogDI;
internal class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.LogToTrace();
}
@@ -1,19 +0,0 @@
{
"profiles": {
"Development": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Staging": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Staging"
}
},
"Production": {
"commandName": "Project"
}
}
}
@@ -1,36 +0,0 @@
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using AvaloniaSerilogDI.ViewModels;
using System;
using System.Diagnostics.CodeAnalysis;
namespace AvaloniaSerilogDI;
// <summary>
/// Given a view model, returns the corresponding view if possible.
/// </summary>
[RequiresUnreferencedCode(
"Default implementation of ViewLocator involves reflection which may be trimmed away.",
Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")]
public class ViewLocator : IDataTemplate
{
public Control? Build(object? param)
{
if (param is null)
return null;
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}
@@ -1,19 +0,0 @@
using LogViewer.Core.ViewModels;
namespace AvaloniaSerilogDI.ViewModels;
public class MainViewModel : ViewModelBase
{
#region Constructor
public MainViewModel(LogViewerControlViewModel logViewer)
=> LogViewer = logViewer;
#endregion
#region Properties
public LogViewerControlViewModel LogViewer { get; }
#endregion
}
@@ -1,7 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace AvaloniaSerilogDI.ViewModels;
public class ViewModelBase : ObservableObject
{
}
@@ -1,19 +0,0 @@
<Window x:Class="AvaloniaSerilogDI.Views.MainWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Window"
xmlns:control="clr-namespace:LogViewer.Avalonia;assembly=LogViewer.Avalonia"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Title="C# AVALONIA SeriLog | LogViewer Control Example - Dot Net 7.0"
Icon="/Assets/avalonia-logo.ico"
WindowStartupLocation="CenterScreen" Height="634" Width="600">
<control:LogViewerControl DataContext="{Binding LogViewer}" />
</Window>
@@ -1,8 +0,0 @@
using Avalonia.Controls;
namespace AvaloniaSerilogDI.Views;
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
}
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embeded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="AvaloniaTest.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
@@ -1,45 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"System.Net.Http.HttpClient": "Trace"
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"LevelSwitches": { "controlSwitch": "Verbose" },
"MinimumLevel": {
"Default": "Verbose",
"Override": {
"Microsoft": "Verbose"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {EventId} | {Message:lj} {NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "c:\\WIP\\LogData\\log-.txt",
"rollingInterval": "Day",
"rollOnFileSizeLimit": true,
"outputTemplate": "{Timestamp:G} {Message}{NewLine:1}{Exception:1}"
}
},
{
"Name": "File",
"Args": {
"path": "c:\\WIP\\LogData\\log-.json",
"rollingInterval": "Day",
"rollOnFileSizeLimit": true,
"formatter": "Serilog.Formatting.Json.JsonFormatter"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ]
}
}
@@ -1,46 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"System.Net.Http.HttpClient": "Warning"
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"LevelSwitches": { "controlSwitch": "Warning" },
"MinimumLevel": {
"Default": "Warning",
"Override": {
"Microsoft": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {EventId.Name} | {Message:lj} {NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "c:\\WIP\\LogData\\log-.txt",
"rollingInterval": "Day",
"rollOnFileSizeLimit": true,
"outputTemplate": "{Timestamp:G} {Message}{NewLine:1}{Exception:1}"
}
},
{
"Name": "File",
"Args": {
"path": "c:\\WIP\\LogData\\log-.json",
"rollingInterval": "Day",
"rollOnFileSizeLimit": true,
"formatter": "Serilog.Formatting.Json.JsonFormatter"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ]
}
}
@@ -1,46 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"System.Net.Http.HttpClient": "Information"
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"LevelSwitches": { "controlSwitch": "Information" },
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {EventId.Name} | {Message:lj} {NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "c:\\WIP\\LogData\\log-.txt",
"rollingInterval": "Day",
"rollOnFileSizeLimit": true,
"outputTemplate": "{Timestamp:G} {Message}{NewLine:1}{Exception:1}"
}
},
{
"Name": "File",
"Args": {
"path": "c:\\WIP\\LogData\\log-.json",
"rollingInterval": "Day",
"rollOnFileSizeLimit": true,
"formatter": "Serilog.Formatting.Json.JsonFormatter"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ]
}
}
@@ -45,7 +45,5 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Background Services\RandomLogging.Service\RandomLogging.Service.csproj" /> <ProjectReference Include="..\..\Background Services\RandomLogging.Service\RandomLogging.Service.csproj" />
<ProjectReference Include="..\..\Controls\LogViewer.Avalonia\LogViewer.Avalonia.csproj" /> <ProjectReference Include="..\..\Controls\LogViewer.Avalonia\LogViewer.Avalonia.csproj" />
<ProjectReference Include="..\..\Core\Common.Core\Common.Core.csproj" />
<ProjectReference Include="..\..\Core\Serilog.Sinks.LogView.Core\Serilog.Sinks.LogView.Core.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -1,4 +1,4 @@
using LogViewer.Core; using Serilog.Sinks.LogView.Core.Logging;
using LogDataStore = LogViewer.Avalonia.Logging.LogDataStore; using LogDataStore = LogViewer.Avalonia.Logging.LogDataStore;
namespace AvaloniaSerilogNoDI.DataStores; namespace AvaloniaSerilogNoDI.DataStores;
@@ -1,45 +1,41 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System;
using System.IO;
namespace Common.Core; namespace AvaloniaSerilogNoDI.Helpers;
public class AppSettings<TOption> public class AppSettings<TOption>
{ {
#region Constructors #region Constructors
public AppSettings(IConfigurationSection configSection, string? key = null) public AppSettings(IConfigurationSection configSection, string? key = null)
{ {
_configSection = configSection; ConfigSection = configSection;
// ReSharper disable once VirtualMemberCallInConstructor // ReSharper disable once VirtualMemberCallInConstructor
GetValue(key); GetValue(key);
} }
#endregion
#region Fields
protected static AppSettings<TOption>? _appSetting;
// ReSharper disable once StaticMemberInGenericType
protected static IConfigurationSection? _configSection;
#endregion #endregion
#region Properties #region Properties
protected static AppSettings<TOption>? AppSetting { get; private set; }
// ReSharper disable once StaticMemberInGenericType
protected static IConfigurationSection? ConfigSection { get; private set; }
public TOption? Value { get; set; } public TOption? Value { get; set; }
#endregion #endregion
#region Methods #region Methods
#pragma warning disable CA1000 // Do not declare static members on generic types
public static TOption? Current(string section, string? key = null) public static TOption? Current(string section, string? key = null)
{ {
_appSetting = GetCurrentSettings(section, key); AppSetting = GetCurrentSettings(section, key);
return _appSetting.Value; return AppSetting.Value;
} }
public static AppSettings<TOption> GetCurrentSettings(string section, string? key = null) public static AppSettings<TOption> GetCurrentSettings(string section, string? key = null)
#pragma warning restore CA1000 // Do not declare static members on generic types
{ {
string env = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production"; string env = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production";
@@ -65,7 +61,7 @@ public class AppSettings<TOption>
{ {
// no key, so must be a class/strut object // no key, so must be a class/strut object
Value = Activator.CreateInstance<TOption>(); Value = Activator.CreateInstance<TOption>();
_configSection!.Bind(Value); ConfigSection!.Bind(Value);
return; return;
} }
@@ -77,10 +73,10 @@ public class AppSettings<TOption>
optionType == typeof(decimal) || optionType == typeof(decimal) ||
optionType == typeof(float) || optionType == typeof(float) ||
optionType == typeof(double)) optionType == typeof(double))
&& _configSection != null) && ConfigSection != null)
{ {
// we must be retrieving a value // we must be retrieving a value
Value = _configSection.GetValue<TOption>(key); Value = ConfigSection.GetValue<TOption>(key);
return; return;
} }
@@ -1,19 +1,30 @@
using AvaloniaSerilogNoDI.DataStores; using AvaloniaSerilogNoDI.DataStores;
using Common.Core.Extensions;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Serilog; using Serilog;
using Serilog.Sinks.LogView.Core; using Serilog.Sinks.LogView.Core.Extensions;
using System;
using System.Drawing; using System.Drawing;
using System.Globalization; using System.Globalization;
using System.IO;
namespace AvaloniaSerilogNoDI.Helpers; namespace AvaloniaSerilogNoDI.Helpers;
// application-wide DataStoreLogger Factory ... returns a wired up Logger instance // application-wide DataStoreLogger Factory ... returns a wired up Logger instance
public static class LoggingHelper public static class LoggingHelper
{ {
#region Constructors public static IConfigurationBuilder Initialize(this IConfigurationBuilder builder)
{
string env = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production";
return builder
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
}
#region Constructors
static LoggingHelper() static LoggingHelper()
{ {
IConfigurationRoot configuration = new ConfigurationBuilder() IConfigurationRoot configuration = new ConfigurationBuilder()
@@ -10,8 +10,8 @@
xmlns:control="clr-namespace:LogViewer.Avalonia;assembly=LogViewer.Avalonia" xmlns:control="clr-namespace:LogViewer.Avalonia;assembly=LogViewer.Avalonia"
Title="C# AVALONIA | SeriLog LogViewer Control Example - Dot Net 7.0" Title="AvaloniaLoggingNoDI-SerilogLogger"
Icon="/Assets/avalonia-logo.ico" Icon="/Assets/avalonia-logo.ico"
WindowStartupLocation="CenterScreen" Height="634" Width="600"> WindowStartupLocation="CenterScreen" Height="634" Width="600">
<control:LogViewerControl x:Name="LogViewerControl" /> <control:LogViewerControl x:Name="LogViewerControl" />
@@ -1,9 +1,9 @@
using Avalonia.Controls; using Avalonia.Controls;
using AvaloniaSerilogNoDI.DataStores; using AvaloniaSerilogNoDI.DataStores;
using AvaloniaSerilogNoDI.Helpers; using AvaloniaSerilogNoDI.Helpers;
using LogViewer.Core;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using RandomLogging.Service; using RandomLogging.Service;
using Serilog.Sinks.LogView.Core.Logging;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Reflection; using System.Reflection;
@@ -11,7 +11,7 @@ using System.Threading;
namespace AvaloniaSerilogNoDI; namespace AvaloniaSerilogNoDI;
public partial class MainWindow : Window, ILogDataStoreImpl public partial class MainWindow : Window, ILogDataStoreCore
{ {
#region Constructors #region Constructors
@@ -20,11 +20,11 @@ public partial class MainWindow : Window, ILogDataStoreImpl
InitializeComponent(); InitializeComponent();
// Initialize _service and pass in the Logger // Initialize _service and pass in the Logger
_service = new(new Logger<RandomLoggingService>(LoggingHelper.Factory)); Service = new(new Logger<RandomLoggingService>(LoggingHelper.Factory));
// Get the Launch mode // Get the Launch mode
bool isDevelopment = string.Equals(Environment.GetEnvironmentVariable("DOTNET_MODIFIABLE_ASSEMBLIES"), "debug", bool isDevelopment = string.Equals(Environment.GetEnvironmentVariable("DOTNET_MODIFIABLE_ASSEMBLIES"), "debug",
StringComparison.InvariantCultureIgnoreCase); StringComparison.OrdinalIgnoreCase);
// initialize a logger & EventId // initialize a logger & EventId
Logger<MainWindow> logger = new Logger<MainWindow>(LoggingHelper.Factory); Logger<MainWindow> logger = new Logger<MainWindow>(LoggingHelper.Factory);
@@ -37,7 +37,7 @@ public partial class MainWindow : Window, ILogDataStoreImpl
logger.Emit(eventId, LogLevel.Information, $"Running in {(isDevelopment ? "Debug" : "Release")} mode"); logger.Emit(eventId, LogLevel.Information, $"Running in {(isDevelopment ? "Debug" : "Release")} mode");
// Start generating log entries // Start generating log entries
_ = _service.StartAsync(CancellationToken.None); _ = Service.StartAsync(CancellationToken.None);
// manually wire up the logging to the view ... the control will show backlog entries... // manually wire up the logging to the view ... the control will show backlog entries...
DataStore = MainControlsDataStore.DataStore; DataStore = MainControlsDataStore.DataStore;
@@ -52,11 +52,8 @@ public partial class MainWindow : Window, ILogDataStoreImpl
#endregion #endregion
#region Fields
private readonly RandomLoggingService? _service; private RandomLoggingService? Service { get; set;}
#endregion
#region Properties #region Properties
@@ -71,7 +68,7 @@ public partial class MainWindow : Window, ILogDataStoreImpl
{ {
Window.Closing -= OnClosing; Window.Closing -= OnClosing;
_ = _service?.StopAsync(); _ = Service?.StopAsync();
LoggingHelper.CloseAndFlush(); LoggingHelper.CloseAndFlush();
} }
@@ -3,7 +3,7 @@ using System;
namespace AvaloniaSerilogNoDI; namespace AvaloniaSerilogNoDI;
internal class Program internal sealed class Program
{ {
// Initialization code. Don't use any Avalonia, third-party APIs or any // Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
@@ -10,7 +10,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Core\LogViewer.Core\LogViewer.Core.csproj" /> <ProjectReference Include="..\..\Serilog.Sinks.LogView.Core\Serilog.Sinks.LogView.Core.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -3,12 +3,10 @@ using Microsoft.Extensions.Logging;
namespace RandomLogging.Service; namespace RandomLogging.Service;
public class RandomLoggingService : BackgroundService public class RandomLoggingService(ILogger<RandomLoggingService> logger) : BackgroundService
{ {
#region Constructors
public RandomLoggingService(ILogger<RandomLoggingService> logger) #region Constructors
=> _logger = logger;
#endregion #endregion
@@ -16,7 +14,7 @@ public class RandomLoggingService : BackgroundService
#region Injected #region Injected
private readonly ILogger _logger; private readonly ILogger _logger = logger;
#endregion #endregion
@@ -164,7 +162,7 @@ public class RandomLoggingService : BackgroundService
} }
_logger.Emit(GenerateEventId(), level, GetMessage(), _logger.Emit(GenerateEventId(), level, GetMessage(),
new Exception(_errorMessages[_random.Next(0, _errorMessages.Count)])); new InvalidDataException(_errorMessages[_random.Next(0, _errorMessages.Count)]));
} }
private EventId GenerateEventId() private EventId GenerateEventId()
@@ -0,0 +1,9 @@
using Serilog.Sinks.LogView.Core.Logging;
namespace LogViewer.Avalonia.Extensions;
public class LogViewerControlViewModel(ILogDataStore dataStore) : ILogDataStoreCore
{
public ILogDataStore DataStore { get; set; } = dataStore;
}
@@ -1,10 +1,9 @@
using LogViewer.Core; using Microsoft.Extensions.DependencyInjection;
using LogViewer.Core.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Serilog.Sinks.LogView.Core.Logging;
using LogDataStore = LogViewer.Avalonia.Logging.LogDataStore; using LogDataStore = LogViewer.Avalonia.Logging.LogDataStore;
namespace LogViewer.Avalonia; namespace LogViewer.Avalonia.Extensions;
public static class ServicesExtension public static class ServicesExtension
{ {
@@ -19,7 +19,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Core\LogViewer.Core\LogViewer.Core.csproj" /> <ProjectReference Include="..\..\Serilog.Sinks.LogView.Core\Serilog.Sinks.LogView.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -1,7 +1,7 @@
using System.Collections.Specialized; using System.Collections.Specialized;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using LogViewer.Core; using Serilog.Sinks.LogView.Core.Logging;
namespace LogViewer.Avalonia; namespace LogViewer.Avalonia;
@@ -13,7 +13,7 @@ public partial class LogViewerControl : UserControl
} }
private ILogDataStoreImpl? vm; private ILogDataStoreCore? vm;
private LogModel? item; private LogModel? item;
private void OnDataContextChanged(object? sender, EventArgs e) private void OnDataContextChanged(object? sender, EventArgs e)
@@ -21,7 +21,7 @@ public partial class LogViewerControl : UserControl
if (DataContext is null) if (DataContext is null)
return; return;
vm = (ILogDataStoreImpl)DataContext; vm = (ILogDataStoreCore)DataContext;
vm.DataStore.Entries.CollectionChanged += OnCollectionChanged; vm.DataStore.Entries.CollectionChanged += OnCollectionChanged;
} }
@@ -1,12 +1,13 @@
using Avalonia.Threading; using Avalonia.Threading;
using Serilog.Sinks.LogView.Core.Logging;
namespace LogViewer.Avalonia.Logging; namespace LogViewer.Avalonia.Logging;
public class LogDataStore : Core.LogDataStore public class LogDataStore : Serilog.Sinks.LogView.Core.Logging.LogDataStore
{ {
#region Methods #region Methods
public override async void AddEntry(Core.LogModel logModel) public override async void AddEntry(LogModel logModel)
=> await Dispatcher.UIThread.InvokeAsync(() => base.AddEntry(logModel)); => await Dispatcher.UIThread.InvokeAsync(() => base.AddEntry(logModel));
#endregion #endregion
@@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.5" />
</ItemGroup>
</Project>
@@ -1,17 +0,0 @@
using Microsoft.Extensions.Configuration;
namespace Common.Core.Extensions;
public static class ConfigurationExtension
{
public static IConfigurationBuilder Initialize(this IConfigurationBuilder builder)
{
string env = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production";
return builder
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
}
}
@@ -1,18 +0,0 @@
namespace Common.Core.Extensions;
public static class ServicesExtension
{
public static TModel? TryGetService<TModel>(this IServiceProvider serviceProvider) where TModel : class
{
try
{
return (TModel?)serviceProvider.GetService(typeof(TModel));
}
catch (ObjectDisposedException)
{
// ignore as we do not care...
}
return default;
}
}
@@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Mvvm.Core\Mvvm.Core.csproj" />
</ItemGroup>
</Project>
@@ -1,6 +0,0 @@
namespace LogViewer.Core;
public interface ILogDataStoreImpl
{
public ILogDataStore DataStore { get; }
}
@@ -1,21 +0,0 @@
using Mvvm.Core;
namespace LogViewer.Core.ViewModels;
public class LogViewerControlViewModel : ViewModel, ILogDataStoreImpl
{
#region Constructor
public LogViewerControlViewModel(ILogDataStore dataStore)
{
DataStore = dataStore;
}
#endregion
#region Properties
public ILogDataStore DataStore { get; set; }
#endregion
}
@@ -1,58 +0,0 @@
using System.Diagnostics;
using LogViewer.Core;
using Microsoft.Extensions.Logging;
namespace MsLogger.Core;
public class DataStoreLogger: ILogger
{
// ref: https://learn.microsoft.com/en-us/dotnet/core/extensions/custom-logging-provider
#region Constructor
public DataStoreLogger(string name, Func<DataStoreLoggerConfiguration> getCurrentConfig, ILogDataStore dataStore)
{
(_name, _getCurrentConfig) = (name, getCurrentConfig);
_dataStore = dataStore;
}
#endregion
#region Fields
private readonly ILogDataStore _dataStore;
private readonly string _name;
private readonly Func<DataStoreLoggerConfiguration> _getCurrentConfig;
#endregion
#region methods
public IDisposable BeginScope<TState>(TState state) where TState : notnull => default!;
public bool IsEnabled(LogLevel logLevel) => true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception, string> formatter)
{
// check if we are logging for passed log level
if (!IsEnabled(logLevel))
return;
DataStoreLoggerConfiguration config = _getCurrentConfig();
_dataStore.AddEntry(new()
{
Timestamp = DateTime.UtcNow,
LogLevel = logLevel,
// do we override the default EventId if it exists?
EventId = eventId.Id == 0 && config.EventId != 0 ? config.EventId : eventId,
State = state,
Exception = exception?.Message ?? (logLevel == LogLevel.Error ? state?.ToString() ?? "" : ""),
Color = config.Colors[logLevel],
});
Debug.WriteLine($"--- [{logLevel.ToString()[..3]}] {_name} - {formatter(state, exception!)}");
}
#endregion
}
@@ -1,48 +0,0 @@
using System.Collections.Concurrent;
using LogViewer.Core;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace MsLogger.Core;
public class DataStoreLoggerProvider: ILoggerProvider
{
#region Constructor
public DataStoreLoggerProvider(IOptionsMonitor<DataStoreLoggerConfiguration> config, ILogDataStore dataStore)
{
_dataStore = dataStore;
_currentConfig = config.CurrentValue;
_onChangeToken = config.OnChange(updatedConfig => _currentConfig = updatedConfig);
}
#endregion
#region fields
private DataStoreLoggerConfiguration _currentConfig;
private readonly IDisposable? _onChangeToken;
protected readonly ILogDataStore _dataStore;
protected readonly ConcurrentDictionary<string, DataStoreLogger> _loggers = new();
#endregion
#region Methods
public ILogger CreateLogger(string categoryName)
=> _loggers.GetOrAdd(categoryName, name => new DataStoreLogger(name, GetCurrentConfig, _dataStore));
protected DataStoreLoggerConfiguration GetCurrentConfig()
=> _currentConfig;
public void Dispose()
{
_loggers.Clear();
_onChangeToken?.Dispose();
}
#endregion
}
@@ -1,22 +0,0 @@
using LogViewer.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
namespace MsLogger.Core;
public static class ServicesExtension
{
public static ILoggingBuilder AddDefaultDataStoreLogger(this ILoggingBuilder builder)
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, DataStoreLoggerProvider>());
return builder;
}
public static ILoggingBuilder AddDefaultDataStoreLogger(this ILoggingBuilder builder, Action<DataStoreLoggerConfiguration> configure)
{
builder.AddDefaultDataStoreLogger();
builder.Services.Configure(configure);
return builder;
}
}
@@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.5" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LogViewer.Core\LogViewer.Core.csproj" />
</ItemGroup>
</Project>
-7
View File
@@ -1,7 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
-21
View File
@@ -1,21 +0,0 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Mvvm.Core;
public class ObservableObject : INotifyPropertyChanged
{
protected bool Set<TValue>(ref TValue field, TValue newValue, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<TValue>.Default.Equals(field, newValue)) return false;
field = newValue;
OnPropertyChanged(propertyName);
return true;
}
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
-3
View File
@@ -1,3 +0,0 @@
namespace Mvvm.Core;
public class ViewModel : ObservableObject { /* skip */ }
@@ -2,24 +2,19 @@
using LogViewer.Core; using LogViewer.Core;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Serilog.Core; using Serilog.Core;
using System.Globalization;
using Serilog.Sinks.LogView.Core.Logging;
namespace Serilog.Sinks.LogView.Core; namespace Serilog.Sinks.LogView.Core;
public class DataStoreLoggerSink : ILogEventSink public class DataStoreLoggerSink(
Func<ILogDataStore> dataStoreProvider,
Func<DataStoreLoggerConfiguration>? getCurrentConfig = null,
IFormatProvider? formatProvider = null) : ILogEventSink
{ {
protected readonly Func<ILogDataStore> _dataStoreProvider; protected Func<ILogDataStore> DataStoreProvider { get; } = dataStoreProvider;
private IFormatProvider? FormatProvider { get; } = formatProvider;
private readonly IFormatProvider? _formatProvider; private Func<DataStoreLoggerConfiguration>? GetCurrentConfig { get; } = getCurrentConfig;
private readonly Func<DataStoreLoggerConfiguration>? _getCurrentConfig;
public DataStoreLoggerSink(Func<ILogDataStore> dataStoreProvider,
Func<DataStoreLoggerConfiguration>? getCurrentConfig = null,
IFormatProvider? formatProvider = null)
{
_formatProvider = formatProvider;
_dataStoreProvider = dataStoreProvider;
_getCurrentConfig = getCurrentConfig;
}
public void Emit(LogEvent logEvent) public void Emit(LogEvent logEvent)
{ {
@@ -33,13 +28,13 @@ public class DataStoreLoggerSink : ILogEventSink
_ => LogLevel.Information _ => LogLevel.Information
}; };
DataStoreLoggerConfiguration config = _getCurrentConfig?.Invoke() ?? new DataStoreLoggerConfiguration(); DataStoreLoggerConfiguration config = GetCurrentConfig?.Invoke() ?? new DataStoreLoggerConfiguration();
EventId eventId = EventIdFactory(logEvent); EventId eventId = EventIdFactory(logEvent);
if (eventId.Id == 0 && config.EventId != 0) if (eventId.Id == 0 && config.EventId != 0)
eventId = config.EventId; eventId = config.EventId;
string message = logEvent.RenderMessage(_formatProvider); string message = logEvent.RenderMessage(FormatProvider);
string exception = logEvent.Exception?.Message ?? (logEvent.Level >= LogEventLevel.Error ? message : string.Empty); string exception = logEvent.Exception?.Message ?? (logEvent.Level >= LogEventLevel.Error ? message : string.Empty);
@@ -50,7 +45,7 @@ public class DataStoreLoggerSink : ILogEventSink
protected virtual void AddLogEntry(LogLevel logLevel, EventId eventId, string message, string exception, LogEntryColor color) protected virtual void AddLogEntry(LogLevel logLevel, EventId eventId, string message, string exception, LogEntryColor color)
{ {
ILogDataStore? dataStore = _dataStoreProvider.Invoke(); ILogDataStore? dataStore = DataStoreProvider.Invoke();
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (dataStore == null) if (dataStore == null)
@@ -79,11 +74,11 @@ public class DataStoreLoggerSink : ILogEventSink
// ref: https://stackoverflow.com/a/56722516 // ref: https://stackoverflow.com/a/56722516
StructureValue? value = src as StructureValue; StructureValue? value = src as StructureValue;
LogEventProperty? idProperty = value!.Properties.FirstOrDefault(x => x.Name.Equals("Id")); LogEventProperty? idProperty = value!.Properties.FirstOrDefault(x => x.Name.Equals("Id", StringComparison.Ordinal));
if (idProperty is not null) if (idProperty is not null)
id = int.Parse(idProperty.Value.ToString()); id = int.Parse(idProperty.Value.ToString(),CultureInfo.InvariantCulture);
LogEventProperty? nameProperty = value.Properties.FirstOrDefault(x => x.Name.Equals("Name")); LogEventProperty? nameProperty = value.Properties.FirstOrDefault(x => x.Name.Equals("Name", StringComparison.Ordinal));
if (nameProperty is not null) if (nameProperty is not null)
eventName = nameProperty.Value.ToString().Trim('"'); eventName = nameProperty.Value.ToString().Trim('"');
@@ -1,7 +1,8 @@
using Serilog.Configuration; using Serilog.Configuration;
using LogViewer.Core; using LogViewer.Core;
using Serilog.Sinks.LogView.Core.Logging;
namespace Serilog.Sinks.LogView.Core; namespace Serilog.Sinks.LogView.Core.Extensions;
public static class DataStoreLoggerSinkExtensions public static class DataStoreLoggerSinkExtensions
{ {
@@ -41,8 +41,9 @@ public static class LoggerExtensions
public static void TestPattern(this ILogger logger, EventId eventId) public static void TestPattern(this ILogger logger, EventId eventId)
{ {
Exception exception = new Exception("Test Error Message"); Exception exception = new InvalidDataException("Test Error Message");
#pragma warning disable CA1848 // Use the LoggerMessage delegates
logger.Emit(eventId, LogLevel.Trace, "Trace Test Pattern"); logger.Emit(eventId, LogLevel.Trace, "Trace Test Pattern");
logger.Emit(eventId, LogLevel.Debug, "Debug Test Pattern"); logger.Emit(eventId, LogLevel.Debug, "Debug Test Pattern");
logger.Emit(eventId, LogLevel.Information, "Information Test Pattern"); logger.Emit(eventId, LogLevel.Information, "Information Test Pattern");
@@ -1,5 +1,6 @@
using System.Drawing; using System.Drawing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Serilog.Sinks.LogView.Core.Logging;
namespace LogViewer.Core; namespace LogViewer.Core;
@@ -1,6 +1,6 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
namespace LogViewer.Core; namespace Serilog.Sinks.LogView.Core.Logging;
public interface ILogDataStore public interface ILogDataStore
{ {
@@ -1,4 +1,4 @@
namespace LogViewer.Core; namespace Serilog.Sinks.LogView.Core.Logging;
public interface ILogDataStoreCore public interface ILogDataStoreCore
{ {
@@ -1,6 +1,6 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
namespace LogViewer.Core; namespace Serilog.Sinks.LogView.Core.Logging;
public class LogDataStore : ILogDataStore public class LogDataStore : ILogDataStore
{ {
@@ -1,6 +1,6 @@
using System.Drawing; using System.Drawing;
namespace LogViewer.Core; namespace Serilog.Sinks.LogView.Core.Logging;
public class LogEntryColor public class LogEntryColor
{ {
@@ -1,6 +1,6 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace LogViewer.Core; namespace Serilog.Sinks.LogView.Core.Logging;
public class LogModel public class LogModel
{ {
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@@ -6,10 +6,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" /> <PackageReference Include="Serilog" Version="4.3.1" />
</ItemGroup> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.5" />
<ItemGroup>
<ProjectReference Include="..\LogViewer.Core\LogViewer.Core.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+54
View File
@@ -0,0 +1,54 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
VisualStudioVersion = 18.4.11626.88
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Controls", "Controls", "{E589E611-C328-4D4F-817D-A91D5A1019FB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{006FDAED-6319-4976-B8BA-8D94E4574139}"
ProjectSection(SolutionItems) = preProject
LICENSE = LICENSE
readme.md = readme.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RandomLogging.Service", "CSharp\Background Services\RandomLogging.Service\RandomLogging.Service.csproj", "{18BA2294-FE64-481F-A86F-F5FD84438B66}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogViewer.Avalonia", "CSharp\Controls\LogViewer.Avalonia\LogViewer.Avalonia.csproj", "{C34C889C-4EB3-45F6-83DE-70252D1D67D5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaSerilogNoDI", "CSharp\Applications\AvaloniaSerilogNoDI\AvaloniaSerilogNoDI.csproj", "{4E892500-CF59-43A9-9A27-80D8EE028821}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serilog.Sinks.LogView.Core", "CSharp\Serilog.Sinks.LogView.Core\Serilog.Sinks.LogView.Core.csproj", "{8CCB028B-541F-69E5-085B-EE77E55737E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{18BA2294-FE64-481F-A86F-F5FD84438B66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18BA2294-FE64-481F-A86F-F5FD84438B66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18BA2294-FE64-481F-A86F-F5FD84438B66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18BA2294-FE64-481F-A86F-F5FD84438B66}.Release|Any CPU.Build.0 = Release|Any CPU
{C34C889C-4EB3-45F6-83DE-70252D1D67D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C34C889C-4EB3-45F6-83DE-70252D1D67D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C34C889C-4EB3-45F6-83DE-70252D1D67D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C34C889C-4EB3-45F6-83DE-70252D1D67D5}.Release|Any CPU.Build.0 = Release|Any CPU
{4E892500-CF59-43A9-9A27-80D8EE028821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E892500-CF59-43A9-9A27-80D8EE028821}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E892500-CF59-43A9-9A27-80D8EE028821}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E892500-CF59-43A9-9A27-80D8EE028821}.Release|Any CPU.Build.0 = Release|Any CPU
{8CCB028B-541F-69E5-085B-EE77E55737E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CCB028B-541F-69E5-085B-EE77E55737E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CCB028B-541F-69E5-085B-EE77E55737E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CCB028B-541F-69E5-085B-EE77E55737E4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C34C889C-4EB3-45F6-83DE-70252D1D67D5} = {E589E611-C328-4D4F-817D-A91D5A1019FB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D6A9B467-ED50-40DB-9FFB-5BE745F08DDB}
EndGlobalSection
EndGlobal
-121
View File
@@ -1,121 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
VisualStudioVersion = 18.4.11626.88
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{A3BEB004-4DF7-4281-9A08-8A7BCD4E3CC9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvvm.Core", "CSharp\Core\Mvvm.Core\Mvvm.Core.csproj", "{BB614345-449F-46AD-BE8C-5E2B7616EDE2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogViewer.Core", "CSharp\Core\LogViewer.Core\LogViewer.Core.csproj", "{34F75D8B-6F15-4DE4-8335-FED83557EB8E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{42E99803-0A95-4172-9079-3B8BF8CBDE9F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Controls", "Controls", "{E589E611-C328-4D4F-817D-A91D5A1019FB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Background Services", "Background Services", "{0CDEA51D-46FE-4767-BA2E-8F14582A926D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.Core", "CSharp\Core\Common.Core\Common.Core.csproj", "{1688A0C1-1AE6-49F6-972E-C419E2A3B58F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{006FDAED-6319-4976-B8BA-8D94E4574139}"
ProjectSection(SolutionItems) = preProject
LICENSE = LICENSE
readme.md = readme.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RandomLogging.Service", "CSharp\Background Services\RandomLogging.Service\RandomLogging.Service.csproj", "{18BA2294-FE64-481F-A86F-F5FD84438B66}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MsLogger.Core", "CSharp\Core\MsLogger.Core\MsLogger.Core.csproj", "{0EDAAABD-495D-43A4-BDFB-A0506CAAC07E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LoggerProviders", "LoggerProviders", "{23CB559B-2361-4ED6-8A26-D1B1C2005D65}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MsLogger", "MsLogger", "{8635B709-1D5A-4445-AC45-F99EE264634F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Serilog", "Serilog", "{578FF757-F837-4C23-B2CA-3CF8B016F6A9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serilog.Sinks.LogView.Core", "CSharp\Core\Serilog.Sinks.LogView.Core\Serilog.Sinks.LogView.Core.csproj", "{69763AFC-6182-402D-9418-6A48404C89A0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaLoggingDI", "CSharp\Applications\AvaloniaLoggingDI\AvaloniaLoggingDI.csproj", "{EA97953E-1223-40D5-A568-8932FDC3105E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogViewer.Avalonia", "CSharp\Controls\LogViewer.Avalonia\LogViewer.Avalonia.csproj", "{C34C889C-4EB3-45F6-83DE-70252D1D67D5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaSerilogDI", "CSharp\Applications\AvaloniaSerilogDI\AvaloniaSerilogDI.csproj", "{BCB0601D-E042-4949-8172-7A35A619519C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaSerilogNoDI", "CSharp\Applications\AvaloniaSerilogNoDI\AvaloniaSerilogNoDI.csproj", "{4E892500-CF59-43A9-9A27-80D8EE028821}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaLoggingNoDI", "CSharp\Applications\AvaloniaLoggingNoDI\AvaloniaLoggingNoDI.csproj", "{85C96F55-572A-4FDF-A028-12D27A48FB4D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BB614345-449F-46AD-BE8C-5E2B7616EDE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BB614345-449F-46AD-BE8C-5E2B7616EDE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BB614345-449F-46AD-BE8C-5E2B7616EDE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BB614345-449F-46AD-BE8C-5E2B7616EDE2}.Release|Any CPU.Build.0 = Release|Any CPU
{34F75D8B-6F15-4DE4-8335-FED83557EB8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{34F75D8B-6F15-4DE4-8335-FED83557EB8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34F75D8B-6F15-4DE4-8335-FED83557EB8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34F75D8B-6F15-4DE4-8335-FED83557EB8E}.Release|Any CPU.Build.0 = Release|Any CPU
{1688A0C1-1AE6-49F6-972E-C419E2A3B58F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1688A0C1-1AE6-49F6-972E-C419E2A3B58F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1688A0C1-1AE6-49F6-972E-C419E2A3B58F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1688A0C1-1AE6-49F6-972E-C419E2A3B58F}.Release|Any CPU.Build.0 = Release|Any CPU
{18BA2294-FE64-481F-A86F-F5FD84438B66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18BA2294-FE64-481F-A86F-F5FD84438B66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18BA2294-FE64-481F-A86F-F5FD84438B66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18BA2294-FE64-481F-A86F-F5FD84438B66}.Release|Any CPU.Build.0 = Release|Any CPU
{0EDAAABD-495D-43A4-BDFB-A0506CAAC07E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0EDAAABD-495D-43A4-BDFB-A0506CAAC07E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0EDAAABD-495D-43A4-BDFB-A0506CAAC07E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0EDAAABD-495D-43A4-BDFB-A0506CAAC07E}.Release|Any CPU.Build.0 = Release|Any CPU
{69763AFC-6182-402D-9418-6A48404C89A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69763AFC-6182-402D-9418-6A48404C89A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69763AFC-6182-402D-9418-6A48404C89A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69763AFC-6182-402D-9418-6A48404C89A0}.Release|Any CPU.Build.0 = Release|Any CPU
{EA97953E-1223-40D5-A568-8932FDC3105E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA97953E-1223-40D5-A568-8932FDC3105E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA97953E-1223-40D5-A568-8932FDC3105E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA97953E-1223-40D5-A568-8932FDC3105E}.Release|Any CPU.Build.0 = Release|Any CPU
{C34C889C-4EB3-45F6-83DE-70252D1D67D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C34C889C-4EB3-45F6-83DE-70252D1D67D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C34C889C-4EB3-45F6-83DE-70252D1D67D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C34C889C-4EB3-45F6-83DE-70252D1D67D5}.Release|Any CPU.Build.0 = Release|Any CPU
{BCB0601D-E042-4949-8172-7A35A619519C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BCB0601D-E042-4949-8172-7A35A619519C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BCB0601D-E042-4949-8172-7A35A619519C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BCB0601D-E042-4949-8172-7A35A619519C}.Release|Any CPU.Build.0 = Release|Any CPU
{4E892500-CF59-43A9-9A27-80D8EE028821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E892500-CF59-43A9-9A27-80D8EE028821}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E892500-CF59-43A9-9A27-80D8EE028821}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E892500-CF59-43A9-9A27-80D8EE028821}.Release|Any CPU.Build.0 = Release|Any CPU
{85C96F55-572A-4FDF-A028-12D27A48FB4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85C96F55-572A-4FDF-A028-12D27A48FB4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85C96F55-572A-4FDF-A028-12D27A48FB4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85C96F55-572A-4FDF-A028-12D27A48FB4D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{BB614345-449F-46AD-BE8C-5E2B7616EDE2} = {A3BEB004-4DF7-4281-9A08-8A7BCD4E3CC9}
{34F75D8B-6F15-4DE4-8335-FED83557EB8E} = {A3BEB004-4DF7-4281-9A08-8A7BCD4E3CC9}
{1688A0C1-1AE6-49F6-972E-C419E2A3B58F} = {A3BEB004-4DF7-4281-9A08-8A7BCD4E3CC9}
{18BA2294-FE64-481F-A86F-F5FD84438B66} = {0CDEA51D-46FE-4767-BA2E-8F14582A926D}
{0EDAAABD-495D-43A4-BDFB-A0506CAAC07E} = {23CB559B-2361-4ED6-8A26-D1B1C2005D65}
{23CB559B-2361-4ED6-8A26-D1B1C2005D65} = {A3BEB004-4DF7-4281-9A08-8A7BCD4E3CC9}
{8635B709-1D5A-4445-AC45-F99EE264634F} = {42E99803-0A95-4172-9079-3B8BF8CBDE9F}
{578FF757-F837-4C23-B2CA-3CF8B016F6A9} = {42E99803-0A95-4172-9079-3B8BF8CBDE9F}
{69763AFC-6182-402D-9418-6A48404C89A0} = {23CB559B-2361-4ED6-8A26-D1B1C2005D65}
{EA97953E-1223-40D5-A568-8932FDC3105E} = {8635B709-1D5A-4445-AC45-F99EE264634F}
{C34C889C-4EB3-45F6-83DE-70252D1D67D5} = {E589E611-C328-4D4F-817D-A91D5A1019FB}
{BCB0601D-E042-4949-8172-7A35A619519C} = {578FF757-F837-4C23-B2CA-3CF8B016F6A9}
{4E892500-CF59-43A9-9A27-80D8EE028821} = {578FF757-F837-4C23-B2CA-3CF8B016F6A9}
{85C96F55-572A-4FDF-A028-12D27A48FB4D} = {8635B709-1D5A-4445-AC45-F99EE264634F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D6A9B467-ED50-40DB-9FFB-5BE745F08DDB}
EndGlobalSection
EndGlobal
Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

@@ -1,18 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Avalonia.Resources</RootNamespace>
<TargetFramework>net7.0</TargetFramework>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.18" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
</Project>
-18
View File
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embeded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="AvaloniaTest.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>