Splat 15.2.22

Prefix Reserved
dotnet add package Splat --version 15.2.22                
NuGet\Install-Package Splat -Version 15.2.22                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Splat" Version="15.2.22" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Splat --version 15.2.22                
#r "nuget: Splat, 15.2.22"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Splat as a Cake Addin
#addin nuget:?package=Splat&version=15.2.22

// Install Splat as a Cake Tool
#tool nuget:?package=Splat&version=15.2.22                

NuGet Stats Build Code Coverage <br> <a href="https://www.nuget.org/packages/splat"> <img src="https://img.shields.io/nuget/dt/splat.svg"> </a> <a href="https://reactiveui.net/slack"> <img src="https://img.shields.io/badge/chat-slack-blue.svg"> </a>

<img src="https://github.com/reactiveui/styleguide/blob/master/logo_splat/logo.png?raw=true" width="200" />

Splat

Certain types of things are basically impossible to do in cross-platform mobile code today, yet there's no reason why. Writing a ViewModel that handles loading a gallery of pictures from disk will be completely riddled with #ifdefs and basically unreadable.

Splat aims to fix that, by providing a usable leaky abstraction above platform code. It is leaky, because it always provides an extension method ToNative() and FromNative(), which converts the abstraction to the platform-specific version. Load the image in the cross-platform code, then call ToNative() in your view to actually display it.

What does it do?

Splat currently supports:

  • Cross-platform image loading/saving
  • A port of System.Drawing.Color for portable libraries
  • Cross-platform geometry primitives (PointF, SizeF, RectangleF), as well as a bunch of additional extension methods to make using them easier.
  • A way to detect whether you're in a Unit Test runner / Design Mode
  • A cross-platform logging framework
  • Simple yet flexible Service Location

Core Team

<table> <tbody> <tr> <td align="center" valign="top"> <img width="100" height="100" src="https://github.com/glennawatson.png?s=150"> <br> <a href="https://github.com/glennawatson">Glenn Watson</a> <p>Melbourne, Australia</p> </td> <td align="center" valign="top"> <img width="100" height="100" src="https://github.com/rlittlesii.png?s=150"> <br> <a href="https://github.com/rlittlesii">Rodney Littles II</a> <p>Texas, USA</p> </td> </tr> <tr> <td align="center" valign="top"> <img width="100" height="100" src="https://github.com/dpvreony.png?s=150"> <br> <a href="https://github.com/dpvreony">David Vreony</a> <p>UK</p> </td> <td align="center" valign="top"> <img width="100" height="100" src="https://github.com/chrispulman.png?s=150"> <br> <a href="https://github.com/chrispulman">Chris Pulman</a> <p>UK</p> </td> </tr> </tbody> </table>

How do I install?

Always Be NuGetting. Package contains binaries for:

  • .NET Framework 4.6.2, .NET Framework 4.7.2, .NET Standard 2.0, .NET 6.0, and .NET 8.0
  • Works with:
    • WPF
    • Windows Forms
    • WinUI 3
    • Maui (WinUI, Android, iOS and Mac)
    • Avalonia

Detecting whether you're in a unit test runner

// If true, we are running unit tests
ModeDetector.InUnitTestRunner();  

Service Location

Splat provides a simple service location implementation that is optimized for Desktop and Mobile applications, while still remaining reasonably flexible.

There are 2 parts to the locator design:

  • Locator.Current The property to use to retrieve services. Locator.Current is a static variable that can be set on startup, to adapt Splat to other DI/IoC frameworks. We're currently working from v7 onward to make it easier to use your DI/IoC framework of choice. (see below)
  • Locator.CurrentMutable The property to use to register services

To get a service:

// To get a single service registration
var toaster = Locator.Current.GetService<IToaster>();

// To get all service registrations
var allToasterImpls = Locator.Current.GetServices<IToaster>();

Locator.Current is a static variable that can be set on startup, to adapt Splat to other DI/IoC frameworks. We're currently working from v7 onward to make it easier to use your DI/IoC framework of choice.

The default implementation of Service Location also allows new types to be registered at runtime.

// Create a new Toaster any time someone asks
Locator.CurrentMutable.Register(() => new Toaster(), typeof(IToaster));

// Register a singleton instance
Locator.CurrentMutable.RegisterConstant(new ExtraGoodToaster(), typeof(IToaster));

// Register a singleton which won't get created until the first user accesses it
Locator.CurrentMutable.RegisterLazySingleton(() => new LazyToaster(), typeof(IToaster));

Dependency Injection Source Generator

There is a source generator that will inject constructor and properties. See here for instructions.

Dependency Resolver Packages

For each of the provided dependency resolver adapters, there is a specific package that allows the service locator to be implemented by another ioc container.

Note: When using ReactiveUI and overriding Splat's default behavior, you have to be sure to initialize ReactiveUI before your container finalizes.

Please note: If you are adjusting behaviours of Splat by working with your custom container directly. Please read the relevant projects documentation on REPLACING the registration. If the container supports appending\ multiple registrations you may get undesired behaviours, such as the wrong logger factory being used.

Container NuGet Read Me
Splat.Autofac SplatAutofacBadge Setup Autofac
Splat.DryIoc SplatDryIocBadge Setup DryIoc
Splat.Microsoft.Extensions.DependencyInjection SplatMicrosoftBadge Setup Microsoft DI
Splat.Ninject SplatNinjectBadge Setup Ninject
Splat.SimpleInjector SplatSimpleInjectorBadge Setup Simple Injector

Logging

Splat provides a simple logging proxy for libraries and applications to set up. By default, this logging isn't configured (i.e. it logs to the Null Logger). To set up logging:

  1. Register an implementation of ILogger using Service Location.
  2. In the class in which you want to log stuff, "implement" the IEnableLogger interface (this is a tag interface, no implementation actually needed).
  3. Call the Log method to write log entries:
this.Log().Warn("Something bad happened: {0}", errorMessage);
this.Log().ErrorException("Tried to do a thing and failed", exception);

For static methods, LogHost.Default can be used as the object to write a log entry for. The Static logger uses a different interface from the main logger to allow capture of additional caller context as it doesn't have the details of the class instance etc. when compared to the normal logger. To get the benefit of these you don't need to do much as they are optional parameters at the end of the methods that are utilised by the compiler\framework. Currently we only capture CallerMemberName.

Available logging adapters

Splat has support for the following logging frameworks

Target Package NuGet
Console Splat SplatBadge
Debug Splat SplatBadge
Log4Net Splat.Log4Net SplatLog4NetBadge
Microsoft Extensions Logging Splat.Microsoft.Extensions.Logging SplatMicrosoftExtensionsLoggingBadge
NLog Splat.NLog SplatNLogBadge
Serilog Splat.Serilog SplatSerilogBadge

Log4Net

First configure Log4Net. For guidance see https://logging.apache.org/log4net/release/manual/configuration.html

using Splat.Log4Net;

// then in your service locator initialisation
Locator.CurrentMutable.UseLog4NetWithWrappingFullLogger();

Thanks to @dpvreony for first creating this logger.

Microsoft.Extensions.Logging

First configure Microsoft.Extensions.Logging. For guidance see https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/

using Splat.Microsoft.Extensions.Logging;

// note: this is different from the other adapter extension methods
//       as it needs knowledge of the logger factory
//       also the "container" is how you configured the Microsoft.Logging.Extensions
var loggerFactory = container.Resolve<ILoggerFactory>();
// in theory it could also be
// var loggerFactory = new LoggerFactory();


/// then in your service locator initialisation
Locator.CurrentMutable.UseMicrosoftExtensionsLoggingWithWrappingFullLogger(loggerFactory);

Thanks to @dpvreony for first creating this logger.

NLog

First configure NLog. For guidance see https://github.com/nlog/nlog/wiki/Tutorial and https://github.com/nlog/nlog/wiki/Configuration-file

using Splat.NLog;

//  then in your service locator initialisation
Locator.CurrentMutable.UseNLogWithWrappingFullLogger();

Thanks to @dpvreony for first creating this logger.

Serilog

First configure Serilog. For guidance see https://github.com/serilog/serilog/wiki/Configuration-Basics

using Splat.Serilog;

// Then in your service locator initialisation
Locator.CurrentMutable.UseSerilogFullLogger()

Thanks to @joelweiss for first creating this logger.

Cross platform drawing

Target Package NuGet
Splat.Drawing Splat.Drawing SplatDrawingBadge

Using Cross-Platform Colors and Geometry

// This System.Drawing class works, even on WinRT where it's not supposed to exist
// Also, this works in a Portable Library, in your ViewModel
ProfileBackgroundAccentColor = Color.FromArgb(255, 255, 255, 255);

Later, in the view, we can use it:

ImageView.Background = ViewModel.ProfileBackgroundAccentColor.ToNativeBrush();

If targeting iOS or Mac in a cross-platform solution (e.g. iOS & Android), use the SplatColor class to define colors in your netstandard library (since Cocoa doesn't include System.Drawing.Color).

// In a netstandard library
SplatColor BackgroundColor = SplatColor.Red;
// From an iOS project
UIColor bgColor = ViewModel.BackgroundColor.ToNative();
// From an Android project
Android.Graphics.Color bgColor = ViewModel.BackgroundColor.ToNative();

Cross-platform Image Loading

You can register with the Splat locators.

Locator.CurrentMutable.RegisterPlatformBitmapLoader();

You can then load your images in a cross platform way:

//
// Load an Image
// This code even works in a Portable Library
//

var wc = new WebClient();
Stream imageStream = wc.OpenRead("http://octodex.github.com/images/Professortocat_v2.png");

// IBitmap is a type that provides basic image information such as dimensions
IBitmap profileImage = await BitmapLoader.Current.Load(imageStream, null /* Use original width */, null /* Use original height */);

Then later, in your View:

// ToNative always converts an IBitmap into the type that the platform
// uses, such as UIBitmap on iOS or BitmapSource in WPF
ImageView.Source = ViewModel.ProfileImage.ToNative();

Images can also be loaded from a Resource. On Android, this can either be a Resource ID casted to a string, or the name of the resource as as string (optionally including the extension).

var profileImage = await BitmapLoader.Current.LoadFromResource("DefaultAvatar.png", null, null);

Bitmaps can also be created and saved - actually drawing on the image is beyond the scope of this library, you should do this in your view-specific code.

var blankImage = BitmapLoader.Current.Create(512.0f, 512.0f);
await blankImage.Save(CompressedBitmapFormat.Png, 0.0, File.Open("ItsBlank.png"));

Detecting if you're in design mode

// If true, we are running inside Blend, so don't do anything
PlatformModeDetector.InDesignMode();

Application Performance Monitoring

Application Performance Monitoring is split into the follow sections

  • Error Reporting
  • Feature Usage Tracking
  • View Tracking

The table below shows the support across various APM packages

Product Package NuGet Maturity Level Error Reporting Feature Usage Tracking View Tracking
Appcenter Splat.AppCenter SplatAppcenterBadge Alpha TODO Native Native
Application Insights Splat.ApplicationInsights SplatApplicationInsightsBadge Alpha TODO Native Native
Exceptionless Splat.Exceptionless SplatExceptionlessBadge Alpha TODO Native By Convention
New Relic N\A N\A Not Started TODO TODO TODO
OpenTrace N\A N\A Not Started TODO TODO TODO
Raygun Splat.Raygun SplatRaygunBadge Prototype TODO By Convention By Convention
Goals of the Splat APM feature
  • To sit on top of existing APM libaries using native features where possible, or by using a common convention that gives parity in behaviour. ** Where there is a convention behaviour it will be detailed under the relevant frameworks documentation.
  • To define basic behaviours that are dropped into consuming libraries, for example with ReactiveUI ** Commands ** ViewModels ** Views
Getting started with APM with Splat

Splat comes with a default implementation that pushes events into your active Splat logging framework. This allows for design and testing prior to hooking up a full APM offering.

Error Reporting

TODO

Feature Usage Tracking

The most basic ability for feature usage tracking is to implement the Splat.ApplicationPerformanceMonitoring.IEnableFeatureUsageTracking interface. This has the same behaviour as the logging interface and allows Splat to inject whichever APM platform is registered with the ServiceLocator at initialization.

        /// <summary>
        /// Dummy object for testing IEnableFeatureUsageTracking.
        /// </summary>
        public sealed class TestObjectThatSupportsFeatureUsageTracking : IEnableFeatureUsageTracking
        {
			public async Task SomeFeatureIWantToTrack()
			{
                using (var trackingSession = this.FeatureUsageTrackingSession("featureName"))
                {
					try
					{
						// do some work here.
					}
					catch (Exception exception)
					{
						trackingSession.OnException(exception);
					}
                }
			}
        }

Splat also has the notion of subfeatures, some APM platforms support this natively, others have been done by convention, which will be explained in the relevant library. Splat itself does not dictate when these should be used. It's up to you. You may have a primary feature (such as a search view) and then track buttons, etc. on that view as subfeatures.

        /// <summary>
        /// Dummy object for testing IEnableFeatureUsageTracking.
        /// </summary>
        public sealed class TestObjectThatSupportsFeatureUsageTracking : IEnableFeatureUsageTracking
        {
			public async Task SomeFeatureIWantToTrack()
			{
                using (var mainFeature = this.FeatureUsageTrackingSession("featureName"))
                {
					try
					{
						await DoSubFeature(mainFeature).ConfigureAwait(false);
					}
					catch (Exception exception)
					{
						mainFeature.OnException(exception);
					}
                }
			}

			public async Task SomeFeatureIWantToTrack(IFeatureUsageTrackingSession parentFeature)
			{
                using (var subFeature = parentFeature.SubFeature("subFeatureName"))
                {
					try
					{
						// do some work here.
					}
					catch (Exception exception)
					{
						subFeature.OnException(exception);
					}
                }
			}
        }
View Tracking

TODO

Configuring Appcenter

First configure Appcenter. For guidance see https://docs.microsoft.com/en-us/appcenter/diagnostics/enabling-diagnostics

using Splat.AppCenter;

// then in your service locator initialisation
Locator.CurrentMutable.UseAppcenterApm();
Configuring Application Insights

First configure Application Insights. For guidance see https://docs.microsoft.com/en-us/azure/azure-monitor/app/worker-service

using Splat.ApplicationInsights;

// then in your service locator initialisation
Locator.CurrentMutable.UseApplicationInsightsApm();
Configuring Exceptionless

First configure Exceptionless. For guidance see https://github.com/exceptionless/Exceptionless/wiki/Getting-Started

using Splat.Exceptionless;

// then in your service locator initialisation
Locator.CurrentMutable.UseExceptionlessApm();
Configuring New Relic

New Relic support isn't currently available.

Configuring OpenTrace

OpenTrace support isn't currently available.

Configuring Raygun

First configure Raygun. For guidance see TODO

using Splat.Raygun;

// then in your service locator initialisation
Locator.CurrentMutable.UseRaygunApm();
Testing and developing the APM functionality

The unit tests for this functionality do not generate activity to the relevant platform. The integration tests DO SEND TEST DATA to the relevant platforms, so they need to have the user-secrets configured. There is a script in the \scripts\inttestusersecrets.cmd that shows how to set the relevant secrets up.

Contribute

Splat is developed under an OSI-approved open source license, making it freely usable and distributable, even for commercial use. We ❤ the people who are involved in this project, and we’d love to have you on board, especially if you are just getting started or have never contributed to open-source before.

So here's to you, lovely person who wants to join us — this is how you can support us:

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (115)

Showing the top 5 NuGet packages that depend on Splat:

Package Downloads
akavache.core

An asynchronous, persistent key-value store for desktop and mobile applications on .NET

ReactiveUI

A MVVM framework that integrates with the Reactive Extensions for .NET to create elegant, testable User Interfaces that run on any mobile or desktop platform. This is the base package with the base platform implementations

ReactiveUI.WPF

Contains the ReactiveUI platform specific extensions for Windows Presentation Foundation (WPF)

ReactiveUI.Testing

Provides extensions for testing ReactiveUI based applications

ReactiveUI.XamForms

Contains the ReactiveUI platform specific extensions for Xamarin Forms

GitHub repositories (58)

Showing the top 5 popular GitHub repositories that depend on Splat:

Repository Stars
shadowsocks/shadowsocks-windows
A C# port of shadowsocks
CodeHubApp/CodeHub
CodeHub is an iOS application written using Xamarin
reactiveui/ReactiveUI
An advanced, composable, functional reactive model-view-viewmodel framework for all .NET platforms that is inspired by functional reactive programming. ReactiveUI allows you to abstract mutable state away from your user interfaces, express the idea around a feature in one readable place and improve the testability of your application.
hbons/SparkleShare
Share and collaborate by syncing with any Git repository instantly. Linux, macOS, and Windows.
HearthSim/Hearthstone-Deck-Tracker
A deck tracker and deck manager for Hearthstone on Windows
Version Downloads Last updated
15.2.22 25,000 9/16/2024
15.1.1 269,427 5/16/2024
15.0.1 58,477 5/1/2024
14.8.12 491,786 12/9/2023
14.8.6 32,620 11/2/2023
14.7.1 270,048 7/24/2023
14.6.37 512,157 6/1/2023
14.6.8 468,751 2/1/2023
14.6.1 52,619 12/7/2022
14.5.1 254,854 11/24/2022
14.4.1 1,209,108 7/14/2022
14.3.4 86,126 6/27/2022
14.3.1 212,109 6/25/2022
14.2.27 118,627 6/24/2022
14.2.8 505,697 4/25/2022
14.2.1 86,232 3/27/2022
14.1.58 7,065 3/25/2022
14.1.45 191,407 2/13/2022
14.1.17 111,509 12/22/2021
14.1.1 372,689 11/30/2021
13.1.63 76,649 11/26/2021
13.1.42 77,717 11/3/2021
13.1.30 44,274 10/21/2021
13.1.27 5,337 10/21/2021
13.1.22 22,379 10/1/2021
13.1.10 27,196 9/14/2021
13.1.1 224,404 8/19/2021
12.1.12 26,252 8/18/2021
12.1.6 48,221 8/10/2021
12.1.4 6,874 8/7/2021
12.1.1 8,810 8/4/2021
11.1.1 356,068 5/13/2021
11.0.1 173,559 4/6/2021
10.0.1 1,402,395 1/22/2021
9.8.1 122,926 12/3/2020
9.7.1 69,028 11/11/2020
9.6.1 479,249 10/13/2020
9.5.49 21,666 9/24/2020
9.5.37 26,259 9/4/2020
9.5.35 28,171 8/28/2020
9.5.20 676,597 8/4/2020
9.5.13 23,935 7/28/2020
9.5.6 93,821 7/7/2020
9.5.2 5,948 7/4/2020
9.5.1 1,872 7/4/2020
9.4.5 4,420,535 4/23/2020
9.4.1 94,676 3/30/2020
9.3.11 236,893 1/18/2020
9.3.4 62,884 12/26/2019
9.3.3 17,245 12/22/2019
9.3.1 13,664 12/15/2019
9.2.11 51,569 11/28/2019
9.2.7 8,431 11/21/2019
9.2.6 5,477 11/20/2019
9.2.5 24,503 11/20/2019
9.2.4 4,851 11/20/2019
9.2.1 4,990 11/20/2019
9.1.1 203,228 10/3/2019
9.0.5 299,099 9/20/2019
9.0.4 6,223 9/20/2019
8.3.1 140,134 8/28/2019
8.2.4 69,519 8/5/2019
8.1.1 32,247 7/27/2019
8.0.5 43,878 7/16/2019
8.0.1 63,497 6/30/2019
8.0.0-dotnet3-preview.8 723 6/8/2019
8.0.0-dotnet3-preview.5 1,203 3/3/2019
7.3.7 39,763 6/21/2019
7.3.6 10,977 6/20/2019
7.3.5 819,779 6/14/2019
7.2.1 170,532 5/13/2019
7.1.1 29,916 5/1/2019
7.0.8 100,631 4/9/2019
7.0.1 225,071 3/20/2019
6.1.7 7,371,337 1/20/2019
6.1.5 13,134 1/18/2019
6.1.1 16,747 1/11/2019
6.0.1 18,262 1/11/2019
5.3.3 29,096 1/7/2019
5.2.1 52,734 1/1/2019
5.1.4 177,701 11/21/2018
5.1.3 2,266 11/21/2018
5.1.1 3,096 11/21/2018
5.0.2 143,653 8/20/2018
5.0.1 13,802 8/16/2018
4.0.2 495,826 8/3/2018
4.0.0 263,914 4/25/2018
3.0.0 65,949 3/12/2018
2.0.0 952,041 11/5/2016
1.6.2 2,881,993 3/22/2015
1.6.1 9,589 2/8/2015
1.6.0 364,208 1/3/2015
1.5.1 64,148 10/2/2014
1.5.0 29,217 9/14/2014
1.4.3 4,899 9/11/2014
1.4.2.1 3,950 8/15/2014
1.4.2 3,001 8/15/2014
1.4.1 4,648 8/8/2014
1.4.0 327,019 7/25/2014
1.3.3 112,288 6/9/2014
1.3.2 3,199 6/2/2014
1.3.1 45,242 5/1/2014
1.3.0 3,388 4/2/2014
1.2.1 3,256 3/5/2014
1.2.0 20,747 2/12/2014
1.1.1 34,510 12/17/2013
1.1.0 2,963 12/17/2013
1.0.0 29,852 12/5/2013
0.3.4 3,009 11/7/2013
0.3.3 2,937 10/17/2013
0.3.2 3,008 10/14/2013
0.3.1 3,106 9/27/2013
0.3.0 3,095 7/30/2013
0.2.0 3,215 7/10/2013
0.1.1 9,975 7/1/2013
0.1.0 11,535 7/1/2013