splat

Makes things cross-platform

Github stars Tracking Chart

NuGet Stats Build Status Code Coverage












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

How do I install?

Always Be NuGetting. Package contains binaries for:

  • WPF (.NET 4.5)
  • Windows Forms
  • UWP
  • Xamarin (Android, iOS and Mac)
  • .NET Standard 1.0 and 2.0

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 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][SplatAutofacNuGet], [![SplatAutofacBadge]][SplatAutofacNuGet], [Setup Autofac][SplatAutofacReadme], [Splat.DryIoc][SplatDryIocNuGet], [![SplatDryIocBadge]][SplatDryIocNuGet], [Setup DryIoc][SplatDryIocReadme], [Splat.Microsoft.Extensions.DependencyInjection][SplatMicrosoftNuGet], [![SplatMicrosoftBadge]][SplatMicrosoftNuGet], [Setup Microsoft DI][SplatMicrosoftReadme], [Splat.Ninject][SplatNinjectNuGet], [![SplatNinjectBadge]][SplatNinjectNuGet], [Setup Ninject][SplatNinjectReadme], [Splat.SimpleInjector][SplatSimpleInjectorNuGet], [![SplatSimpleInjectorBadge]][SplatSimpleInjectorNuGet], [SplatAutofacNuGet]: https://www.nuget.org/packages/Splat.Autofac/
[SplatAutofacBadge]: https://img.shields.io/nuget/v/Splat.Autofac.svg
[SplatAutofacReadme]: ./src/Splat.Autofac/README.md
[SplatDryIocNuGet]: https://www.nuget.org/packages/Splat.DryIoc/
[SplatDryIocBadge]: https://img.shields.io/nuget/v/Splat.DryIoc.svg
[SplatDryIocReadme]: ./src/Splat.DryIoc/README.md
[SplatMicrosoftNuGet]: https://www.nuget.org/packages/Splat.Microsoft.Extensions.DependencyInjection/
[SplatMicrosoftBadge]: https://img.shields.io/nuget/v/Splat.Microsoft.Extensions.DependencyInjection.svg
[SplatMicrosoftReadme]: ./src/Splat.Microsoft.Extensions.DependencyInjection/README.md
[SplatNinjectNuGet]: https://www.nuget.org/packages/Splat.Ninject/
[SplatNinjectBadge]: https://img.shields.io/nuget/v/Splat.Ninject.svg
[SplatNinjectReadme]: ./src/Splat.Ninject/README.md
[SplatSimpleInjectorNuGet]: https://www.nuget.org/packages/Splat.SimpleInjector/
[SplatSimpleInjectorBadge]: https://img.shields.io/nuget/v/Splat.SimpleInjector.svg

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.

Available logging adapters

Splat has support for the following logging frameworks, Target, Package, NuGet, ---------, -------, ------, Console, [Splat][SplatNuGet], [![SplatBadge]][SplatNuGet], Debug, [Splat][SplatNuGet], [![SplatBadge]][SplatNuGet], Log4Net, [Splat.Log4Net][SplatLog4NetNuGet], [![SplatLog4NetBadge]][SplatLog4NetNuGet], Microsoft Extensions Logging, [Splat.Microsoft.Extensions.Logging][SplatMicrosoftExtensionsLoggingNuGet], [![SplatMicrosoftExtensionsLoggingBadge]][SplatMicrosoftExtensionsLoggingNuGet], NLog, [Splat.NLog][SplatNLogNuGet], [![SplatNLogBadge]][SplatNLogNuGet], Serilog, [Splat.Serilog][SplatSerilogNuGet], [![SplatSerilogBadge]][SplatSerilogNuGet], [SplatNuGet]: https://www.nuget.org/packages/Splat/
[SplatBadge]: https://img.shields.io/nuget/v/Splat.svg
[SplatLog4NetNuGet]: https://www.nuget.org/packages/Splat.Log4Net/
[SplatLog4NetBadge]: https://img.shields.io/nuget/v/Splat.Log4Net.svg
[SplatMicrosoftExtensionsLoggingNuGet]: https://www.nuget.org/packages/Splat.Microsoft.Extensions.Logging/
[SplatMicrosoftExtensionsLoggingBadge]: https://img.shields.io/nuget/v/Splat.Microsoft.Extensions.Logging.svg
[SplatNLogNuGet]: https://www.nuget.org/packages/Splat.NLog/
[SplatNLogBadge]: https://img.shields.io/nuget/v/Splat.NLog.svg
[SplatSerilogNuGet]: https://www.nuget.org/packages/Splat.Serilog/
[SplatSerilogBadge]: https://img.shields.io/nuget/v/Splat.Serilog.svg

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][SplatDrawingNuGet], [SplatDrawingBadge][SplatDrawingNuGet], [SplatDrawingNuGet]: https://www.nuget.org/packages/Splat.Drawing/

Using Cross-Platform Colors and Geometry

// This System.Drawing class works, even on WinRT or WP8 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();

Contribute

Splat is developed under an OSI-approved open source license, making it freely usable and distributable, even for commercial use. Because of our Open Collective model for funding and transparency, we are able to funnel support and funds through to our contributors and community. 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:

Main metrics

Overview
Name With Ownerreactiveui/splat
Primary LanguageC#
Program languageC# (Language Count: 1)
Platform
License:MIT License
所有者活动
Created At2013-06-30 18:47:46
Pushed At2025-05-10 10:09:21
Last Commit At
Release Count115
Last Release Name15.3.1 (Posted on )
First Release Name0.1.0 (Posted on 2013-07-01 13:15:51)
用户参与
Stargazers Count1k
Watchers Count53
Fork Count141
Commits Count1.3k
Has Issues Enabled
Issues Count190
Issue Open Count14
Pull Requests Count969
Pull Requests Open Count5
Pull Requests Close Count146
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private