diff --git a/DeviceId.sln b/DeviceId.sln
index c23a503..60fbba2 100644
--- a/DeviceId.sln
+++ b/DeviceId.sln
@@ -24,7 +24,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Mac", "src\DeviceI
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Tests", "test\DeviceId.Tests\DeviceId.Tests.csproj", "{C706C3B5-4912-41E6-9EF3-B8560464680A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceId.SqlServer", "src\DeviceId.SqlServer\DeviceId.SqlServer.csproj", "{678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.SqlServer", "src\DeviceId.SqlServer\DeviceId.SqlServer.csproj", "{678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeviceId.Xamarin", "src\DeviceId.Xamarin\DeviceId.Xamarin.csproj", "{114925F8-6BF9-445B-A3A4-BADAD99A3EAB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -64,6 +66,10 @@ Global
{678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{678F5EAE-C13E-4EEC-A2F3-17F43CE099FE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {114925F8-6BF9-445B-A3A4-BADAD99A3EAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {114925F8-6BF9-445B-A3A4-BADAD99A3EAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {114925F8-6BF9-445B-A3A4-BADAD99A3EAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {114925F8-6BF9-445B-A3A4-BADAD99A3EAB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -77,6 +83,7 @@ Global
{865D5271-A21F-4F4B-8F57-7278FEC051AA} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
{C706C3B5-4912-41E6-9EF3-B8560464680A} = {5D030E54-9156-468B-9288-498DE74D8C61}
{678F5EAE-C13E-4EEC-A2F3-17F43CE099FE} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
+ {114925F8-6BF9-445B-A3A4-BADAD99A3EAB} = {BD122A91-437F-497E-80F1-F21BAD62C51F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {702DF5F2-A40A-46BC-A155-7CEAF7F7AA93}
diff --git a/src/DeviceId.Xamarin/DeviceId.Xamarin.csproj b/src/DeviceId.Xamarin/DeviceId.Xamarin.csproj
new file mode 100644
index 0000000..360cf3c
--- /dev/null
+++ b/src/DeviceId.Xamarin/DeviceId.Xamarin.csproj
@@ -0,0 +1,25 @@
+
+
+
+ DeviceId.Xamarin
+ DeviceId (Xamarin)
+ Provides Xamarin-specific components for the DeviceId package.
+ 6.2.0
+
+
+
+ netstandard2.0;net5.0;net6.0
+ latest
+ true
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/DeviceId.Xamarin/DeviceIdBuilderExtensions.cs b/src/DeviceId.Xamarin/DeviceIdBuilderExtensions.cs
new file mode 100644
index 0000000..14fa331
--- /dev/null
+++ b/src/DeviceId.Xamarin/DeviceIdBuilderExtensions.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace DeviceId;
+
+///
+/// Extension methods for .
+///
+public static class DeviceIdBuilderExtensions
+{
+ ///
+ /// Adds Xamarin-specific components to the device ID.
+ ///
+ /// The device ID builder to add the components to.
+ /// An action that adds the Xamarin-specific components.
+ /// The device ID builder.
+ public static DeviceIdBuilder OnLinux(this DeviceIdBuilder builder, Action xamarinBuilderConfiguration)
+ {
+ if (xamarinBuilderConfiguration is not null)
+ {
+ var linuxBuilder = new XamarinDeviceIdBuilder(builder);
+ xamarinBuilderConfiguration.Invoke(linuxBuilder);
+ }
+
+ return builder;
+ }
+}
diff --git a/src/DeviceId.Xamarin/XamarinDeviceIdBuilder.cs b/src/DeviceId.Xamarin/XamarinDeviceIdBuilder.cs
new file mode 100644
index 0000000..97a7ec0
--- /dev/null
+++ b/src/DeviceId.Xamarin/XamarinDeviceIdBuilder.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Runtime.InteropServices;
+using DeviceId.Internal;
+using Xamarin.Essentials;
+
+namespace DeviceId;
+
+///
+/// Provides a fluent interface for adding Xamarin-specific components to a device identifier.
+///
+public class XamarinDeviceIdBuilder
+{
+ ///
+ /// The base device identifier builder.
+ ///
+ private readonly DeviceIdBuilder _baseBuilder;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The base device identifier builder.
+ public XamarinDeviceIdBuilder(DeviceIdBuilder baseBuilder)
+ {
+ _baseBuilder = baseBuilder ?? throw new ArgumentNullException(nameof(baseBuilder));
+ }
+
+ ///
+ /// Adds a component to the device identifier.
+ /// If a component with the specified name already exists, it will be replaced with this newly added component.
+ ///
+ /// The component name.
+ /// The component to add.
+ /// The builder instance.
+ public XamarinDeviceIdBuilder AddComponent(string name, IDeviceIdComponent component)
+ {
+ _baseBuilder.AddComponent(name, component);
+
+ return this;
+ }
+}
diff --git a/src/DeviceId.Xamarin/XamarinDeviceIdBuilderExtensions.cs b/src/DeviceId.Xamarin/XamarinDeviceIdBuilderExtensions.cs
new file mode 100644
index 0000000..511ad0c
--- /dev/null
+++ b/src/DeviceId.Xamarin/XamarinDeviceIdBuilderExtensions.cs
@@ -0,0 +1,103 @@
+using System;
+using DeviceId.Components;
+using Xamarin.Essentials;
+
+namespace DeviceId;
+
+///
+/// Extension methods for .
+///
+public static class XamarinDeviceIdBuilderExtensions
+{
+ ///
+ /// Adds the device manufacturer to the device identifier.
+ ///
+ /// The to add the component to.
+ /// The instance.
+ public static XamarinDeviceIdBuilder AddManufacturer(this XamarinDeviceIdBuilder builder)
+ {
+ return builder.AddComponent("Manufacturer", new TextComponent(DeviceInfo.Manufacturer));
+ }
+
+ ///
+ /// Adds the OS-version to the device identifier.
+ ///
+ /// The to add the component to.
+ /// The instance.
+ public static XamarinDeviceIdBuilder AddOsVersion(this XamarinDeviceIdBuilder builder)
+ {
+ return builder.AddComponent("OSVersion", new TextComponent(DeviceInfo.VersionString));
+ }
+
+ ///
+ /// Adds the device model to the device identifier.
+ ///
+ /// The to add the component to.
+ /// The instance.
+ public static XamarinDeviceIdBuilder AddModel(this XamarinDeviceIdBuilder builder)
+ {
+ return builder.AddComponent("Model", new TextComponent(DeviceInfo.Model));
+ }
+
+ ///
+ /// Adds the device-platform to the device identifier.
+ ///
+ /// The to add the component to.
+ /// The instance.
+ public static XamarinDeviceIdBuilder AddPlatform(this XamarinDeviceIdBuilder builder)
+ {
+ return builder.AddComponent("Platform", new TextComponent(DeviceInfo.Platform.ToString()));
+ }
+
+ ///
+ /// Adds the device type (physical/virtual) to the device identifier.
+ ///
+ /// The to add the component to.
+ /// The instance.
+ public static XamarinDeviceIdBuilder AddDeviceType(this XamarinDeviceIdBuilder builder)
+ {
+ return builder.AddComponent("DeviceType", new TextComponent(DeviceInfo.DeviceType.ToString()));
+ }
+
+ ///
+ /// Adds the device idiom to the device identifier (phone, tablet, watch , ...).
+ ///
+ /// The to add the component to.
+ /// The instance.
+ public static XamarinDeviceIdBuilder AddIdiom(this XamarinDeviceIdBuilder builder)
+ {
+ return builder.AddComponent("Idiom", new TextComponent(DeviceInfo.Idiom.ToString()));
+ }
+
+ ///
+ /// Adds the device name to the device identifier.
+ ///
+ /// The to add the component to.
+ /// The instance.
+ public static XamarinDeviceIdBuilder AddDeviceName(this XamarinDeviceIdBuilder builder)
+ {
+ return builder.AddComponent("DeviceName", new TextComponent(DeviceInfo.Name));
+ }
+
+ ///
+ /// Adds a generated guid to the device identifier. The generated value is persistantly stored.
+ ///
+ /// The to add the component to.
+ /// The instance.
+ public static XamarinDeviceIdBuilder AddGeneratedGuid(this XamarinDeviceIdBuilder builder)
+ {
+ const string key = "XamarinDeviceIdBuilder.GeneratedId";
+ Func func = () =>
+ {
+ string guid = Preferences.Get(key, "");
+ if (string.IsNullOrEmpty(guid))
+ {
+ guid = Guid.NewGuid().ToString();
+ Preferences.Set(key, guid);
+ }
+ return guid;
+ };
+ return builder.AddComponent("GeneratedGuid", new FuncComponent(func));
+ }
+
+}
diff --git a/src/DeviceId.Xamarin/_InternalsVisibleTo.cs b/src/DeviceId.Xamarin/_InternalsVisibleTo.cs
new file mode 100644
index 0000000..8f018f5
--- /dev/null
+++ b/src/DeviceId.Xamarin/_InternalsVisibleTo.cs
@@ -0,0 +1,4 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
+[assembly: InternalsVisibleTo("DeviceId.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001008906d2e5a92d72693cfdd24b29f9c3ea5ca51972be746724afef8a65000a1ebbc88aee54e4c9c3bef49c0e837702170e99919a8b8075cfd6ed8494c5f9cd1a640a57cc907a84861bfe7ecb877d475a94ec333c6c0a586b6f37a15e67431381cac046217c0fa570c3e8e140e733254686213b77ae53fccdc1f5b3ab806ac692c1")]
diff --git a/src/DeviceId/Components/FuncComponent.cs b/src/DeviceId/Components/FuncComponent.cs
new file mode 100644
index 0000000..17eade0
--- /dev/null
+++ b/src/DeviceId/Components/FuncComponent.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace DeviceId.Components;
+
+///
+/// An implementation of that executes a command.
+///
+public class FuncComponent : IDeviceIdComponent
+{
+ private readonly Func _func;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value-function of this component.
+ internal FuncComponent(Func func)
+ {
+ _func = func;
+ }
+
+ ///
+ /// Gets the component value.
+ ///
+ /// The component value.
+ public string GetValue()
+ {
+ return _func.Invoke();
+ }
+}
diff --git a/src/DeviceId/Components/TextComponent.cs b/src/DeviceId/Components/TextComponent.cs
new file mode 100644
index 0000000..4c43206
--- /dev/null
+++ b/src/DeviceId/Components/TextComponent.cs
@@ -0,0 +1,27 @@
+namespace DeviceId.Components;
+
+///
+/// An implementation of that executes a command.
+///
+public class TextComponent : IDeviceIdComponent
+{
+ private readonly string _value;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value of this component.
+ internal TextComponent(string value)
+ {
+ _value = value;
+ }
+
+ ///
+ /// Gets the component value.
+ ///
+ /// The component value.
+ public string GetValue()
+ {
+ return _value;
+ }
+}
diff --git a/src/DeviceId/_InternalsVisibleTo.cs b/src/DeviceId/_InternalsVisibleTo.cs
index f5994c3..37175f9 100644
--- a/src/DeviceId/_InternalsVisibleTo.cs
+++ b/src/DeviceId/_InternalsVisibleTo.cs
@@ -8,3 +8,4 @@
[assembly: InternalsVisibleTo("DeviceId.Windows.Wmi, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5bb1a0001be3481cbd50b4a86a99d4ce1f71eff5631fbacae0016ecc5273209aa9ab743f14cf1d370e63a039b9079326a35de058cc1f5f40ba86faf4ac8679ecc04241da2edc94e20582d00455cefbd484a124a1ecde382ff5281f6375c3efd96efdea6c6da248c1daa4ab8a4db0a325afd531668a67d5617d1bd0ad7c40dda")]
[assembly: InternalsVisibleTo("DeviceId.Linux, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5bb1a0001be3481cbd50b4a86a99d4ce1f71eff5631fbacae0016ecc5273209aa9ab743f14cf1d370e63a039b9079326a35de058cc1f5f40ba86faf4ac8679ecc04241da2edc94e20582d00455cefbd484a124a1ecde382ff5281f6375c3efd96efdea6c6da248c1daa4ab8a4db0a325afd531668a67d5617d1bd0ad7c40dda")]
[assembly: InternalsVisibleTo("DeviceId.Mac, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5bb1a0001be3481cbd50b4a86a99d4ce1f71eff5631fbacae0016ecc5273209aa9ab743f14cf1d370e63a039b9079326a35de058cc1f5f40ba86faf4ac8679ecc04241da2edc94e20582d00455cefbd484a124a1ecde382ff5281f6375c3efd96efdea6c6da248c1daa4ab8a4db0a325afd531668a67d5617d1bd0ad7c40dda")]
+[assembly: InternalsVisibleTo("DeviceId.Xamarin, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5bb1a0001be3481cbd50b4a86a99d4ce1f71eff5631fbacae0016ecc5273209aa9ab743f14cf1d370e63a039b9079326a35de058cc1f5f40ba86faf4ac8679ecc04241da2edc94e20582d00455cefbd484a124a1ecde382ff5281f6375c3efd96efdea6c6da248c1daa4ab8a4db0a325afd531668a67d5617d1bd0ad7c40dda")]