Merge branch 'master' into jamesmcroft/3506-carousel-automation
This commit is contained in:
Коммит
df21fcac0b
|
@ -7,7 +7,9 @@ assignees: ''
|
|||
|
||||
---
|
||||
|
||||
<!-- 🚨 Please Do Not skip any instructions and information mentioned below as they are all required and essential to investigate the issue. Issues with missing information may be closed without investigation 🚨 -->
|
||||
<!-- 🚨 PLEASE DO NOT SKIP ANY INSTRUCTIONS AND INFORMATION MENTIONED BELOW AS THEY ARE ALL REQUIRED AND ESSENTIAL TO INVESTIGATE THE ISSUE. ISSUES WITH MISSING INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION
|
||||
...
|
||||
IF NOT CERTAIN ABOUT THE ISSUE AND REQUIRE MORE CLARITY THEN PLEASE POST ON "QUESTIONS & HELP" CATEGORY OF THE DISCUSSIONS PLATFORM [https://github.com/windows-toolkit/WindowsCommunityToolkit/discussions/categories/questions-help] WHERE YOU CAN DISCUSS AND ENAGAGE WITH THE COMMUNITY TO GAIN FURTHER CLAIRITY REGARDING THE ISSUE 🚨 -->
|
||||
|
||||
## Describe the bug
|
||||
A clear and concise description of what the bug is.
|
||||
|
|
|
@ -7,7 +7,9 @@ assignees: ''
|
|||
|
||||
---
|
||||
|
||||
<!-- 🚨 Please provide detailed information and Do Not skip any instructions as they are all required and essential to help us understand the feature 🚨 -->
|
||||
<!-- 🚨 PLEASE PROVIDE DETAILED INFORMATION AND DO NOT SKIP ANY INSTRUCTIONS AND INFORMATION MENTIONED BELOW AS THEY ARE ALL REQUIRED AND ESSENTIAL TO HELP US UNDERSTAND THE FEATURE.
|
||||
...
|
||||
IF NOT CERTAIN ABOUT THE FEATURE AND REQUIRE MORE CLARITY THEN PLEASE POST ON "IDEAS" CATEGORY OF THE DISCUSSIONS PLATFORM [https://github.com/windows-toolkit/WindowsCommunityToolkit/discussions/categories/ideas] WHERE YOU CAN DISCUSS AND ENAGAGE WITH THE COMMUNITY TO GAIN FURTHER CLAIRITY REGARDING THE FEATURE 🚨 -->
|
||||
|
||||
## Describe the problem this feature would solve
|
||||
<!-- Please describe or link to any existing issues or discussions.
|
||||
|
|
|
@ -12,8 +12,9 @@ Hi!
|
|||
|
||||
We try and keep our GitHub issue list for bugs and features.
|
||||
|
||||
Ideally, it'd be great to post your question on Stack Overflow using the 'windows-community-toolkit' tag here: https://stackoverflow.com/questions/tagged/windows-community-toolkit
|
||||
🚨 Please provide detailed information that includes examples, screenshots, and relevant issues if possible 🚨
|
||||
Ideally, it'd be great to post your question on Stack Overflow using the 'windows-community-toolkit' tag here: https://stackoverflow.com/questions/tagged/windows-community-toolkit OR you may ask the question on "Questions & Help" category of the Discussions platform [https://github.com/windows-toolkit/WindowsCommunityToolkit/discussions/categories/questions-help]
|
||||
|
||||
🚨 PLEASE PROVIDE DETAILED INFORMATION THAT INCLUDE EXAMPLES, SCREENSHOTS, AND RELEVANT ISSUES IF POSSIBLE 🚨
|
||||
|
||||
If this is more about a scenario that you think is missing documentation, please file an issue instead at https://github.com/MicrosoftDocs/WindowsCommunityToolkitDocs/issues/new
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/windows-toolkit/WindowsCommunityToolkit/master/build/nuget.png</PackageIconUrl>
|
||||
<PackageIcon>images\nuget.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/windows-toolkit/WindowsCommunityToolkit</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/windows-toolkit/WindowsCommunityToolkit/blob/master/license.md</PackageLicenseUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageReleaseNotes>https://github.com/windows-toolkit/WindowsCommunityToolkit/releases</PackageReleaseNotes>
|
||||
<Copyright>(c) .NET Foundation and Contributors. All rights reserved.</Copyright>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
|
@ -95,13 +96,15 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.1.91" PrivateAssets="all" />
|
||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json">
|
||||
<Link>stylecop.json</Link>
|
||||
</AdditionalFiles>
|
||||
<None Include="$(MSBuildThisFileDirectory)license.md" Pack="true" PackagePath="\"/>
|
||||
<None Include="$(MSBuildThisFileDirectory)build\nuget.png" Pack="true" PackagePath="images\"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)build\Windows.Toolkit.VisualStudio.Design.props" Condition="'$(IsDesignProject)' == 'true'"/>
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.10</Version>
|
||||
<Version>6.2.12</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="StyleCop.Analyzers">
|
||||
<Version>1.0.2</Version>
|
||||
|
|
|
@ -11,7 +11,7 @@ using System.Reflection;
|
|||
#endif
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.Toolkit.Extensions
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with types.
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Diagnostics.Contracts;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Toolkit.Extensions
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with value types.
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -6,9 +6,6 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
#if NETSTANDARD1_4
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Contracts;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.Diagnostics
|
||||
{
|
||||
|
|
|
@ -9,7 +9,6 @@ using System.Diagnostics.Contracts;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers.Views;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Buffers
|
||||
|
|
|
@ -7,7 +7,6 @@ using System.Buffers;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers.Internals.Interfaces;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Buffers.Internals
|
||||
|
|
|
@ -8,7 +8,7 @@ using System;
|
|||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Buffers.Internals
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ namespace Microsoft.Toolkit.HighPerformance.Buffers.Internals
|
|||
/// <inheritdoc/>
|
||||
public override Span<T> GetSpan()
|
||||
{
|
||||
ref T r0 = ref this.instance.DangerousGetObjectDataReferenceAt<T>(this.offset);
|
||||
ref T r0 = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(this.instance, this.offset);
|
||||
|
||||
return MemoryMarshal.CreateSpan(ref r0, this.length);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ namespace Microsoft.Toolkit.HighPerformance.Buffers.Internals
|
|||
// traditional means (eg. via the implicit T[] array conversion), if T is a
|
||||
// reference type or a type containing some references.
|
||||
GCHandle handle = GCHandle.Alloc(this.instance, GCHandleType.Pinned);
|
||||
ref T r0 = ref this.instance.DangerousGetObjectDataReferenceAt<T>(this.offset);
|
||||
ref T r0 = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(this.instance, this.offset);
|
||||
ref T r1 = ref Unsafe.Add(ref r0, (nint)(uint)elementIndex);
|
||||
void* p = Unsafe.AsPointer(ref r1);
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ using System.Buffers;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers.Internals.Interfaces;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Buffers.Internals
|
||||
|
|
|
@ -11,7 +11,6 @@ using System.Runtime.CompilerServices;
|
|||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers.Views;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Buffers
|
||||
{
|
||||
|
|
|
@ -11,7 +11,6 @@ using System.Runtime.CompilerServices;
|
|||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers.Views;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Buffers
|
||||
{
|
||||
|
|
|
@ -7,7 +7,6 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
#if !NETSTANDARD1_4
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,6 @@ using System.Runtime.CompilerServices;
|
|||
#if SPAN_RUNTIME_SUPPORT
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Internals;
|
||||
|
||||
|
|
|
@ -76,7 +76,16 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables
|
|||
{
|
||||
this.start = newEnd;
|
||||
|
||||
int index = this.span.Slice(newEnd).IndexOf(this.separator);
|
||||
// We need to call this extension explicitly or the extension method resolution rules for the C# compiler
|
||||
// will end up picking Microsoft.Toolkit.HighPerformance.ReadOnlySpanExtensions.IndexOf instead, even
|
||||
// though the latter takes the parameter via a readonly reference. This is because the "in" modifier is
|
||||
// implicit, which makes the signature compatible, and because extension methods are matched in such a
|
||||
// way that methods "closest" to where they're used are preferred. Since this type shares the same root
|
||||
// namespace, this makes that extension a better match, so that it overrides the MemoryExtensions one.
|
||||
// This is not a problem for consumers of this package, as their code would be outside of the
|
||||
// Microsoft.Toolkit.HighPerformance namespace, so both extensions would be "equally distant", so that
|
||||
// when they're both in scope it will be possible to choose which one to use by adding an explicit "in".
|
||||
int index = System.MemoryExtensions.IndexOf(this.span.Slice(newEnd), this.separator);
|
||||
|
||||
// Extract the current subsequence
|
||||
if (index >= 0)
|
||||
|
|
|
@ -8,7 +8,6 @@ using System.Runtime.CompilerServices;
|
|||
#if SPAN_RUNTIME_SUPPORT
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
#if SPAN_RUNTIME_SUPPORT
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Internals;
|
||||
|
|
|
@ -9,10 +9,13 @@ using System.Runtime.CompilerServices;
|
|||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Enumerables;
|
||||
#if !NETCORE_RUNTIME && !NET5_0
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="Array"/> type.
|
||||
|
@ -40,7 +43,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
#else
|
||||
IntPtr offset = RuntimeHelpers.GetArrayDataByteOffset<T>();
|
||||
|
||||
return ref array.DangerousGetObjectDataReferenceAt<T>(offset);
|
||||
return ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -69,7 +72,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
return ref ri;
|
||||
#else
|
||||
IntPtr offset = RuntimeHelpers.GetArrayDataByteOffset<T>();
|
||||
ref T r0 = ref array.DangerousGetObjectDataReferenceAt<T>(offset);
|
||||
ref T r0 = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, offset);
|
||||
ref T ri = ref Unsafe.Add(ref r0, (nint)(uint)i);
|
||||
|
||||
return ref ri;
|
||||
|
|
|
@ -10,10 +10,11 @@ using System.Runtime.InteropServices;
|
|||
using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Enumerables;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="Array"/> type.
|
||||
|
@ -39,7 +40,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
#else
|
||||
IntPtr offset = RuntimeHelpers.GetArray2DDataByteOffset<T>();
|
||||
|
||||
return ref array.DangerousGetObjectDataReferenceAt<T>(offset);
|
||||
return ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -72,7 +73,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
int width = array.GetLength(1);
|
||||
nint index = ((nint)(uint)i * (nint)(uint)width) + (nint)(uint)j;
|
||||
IntPtr offset = RuntimeHelpers.GetArray2DDataByteOffset<T>();
|
||||
ref T r0 = ref array.DangerousGetObjectDataReferenceAt<T>(offset);
|
||||
ref T r0 = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, offset);
|
||||
ref T ri = ref Unsafe.Add(ref r0, index);
|
||||
|
||||
return ref ri;
|
||||
|
@ -137,7 +138,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
return new RefEnumerable<T>(ref r0, width, 1);
|
||||
#else
|
||||
ref T r0 = ref array.DangerousGetReferenceAt(row, 0);
|
||||
IntPtr offset = array.DangerousGetObjectDataByteOffset(ref r0);
|
||||
IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref r0);
|
||||
|
||||
return new RefEnumerable<T>(array, offset, width, 1);
|
||||
#endif
|
||||
|
@ -191,7 +192,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
return new RefEnumerable<T>(ref r0, height, width);
|
||||
#else
|
||||
ref T r0 = ref array.DangerousGetReferenceAt(0, column);
|
||||
IntPtr offset = array.DangerousGetObjectDataByteOffset(ref r0);
|
||||
IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref r0);
|
||||
|
||||
return new RefEnumerable<T>(array, offset, height, width);
|
||||
#endif
|
||||
|
@ -324,7 +325,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
}
|
||||
|
||||
ref T r0 = ref array.DangerousGetReferenceAt(row, 0);
|
||||
IntPtr offset = array.DangerousGetObjectDataByteOffset(ref r0);
|
||||
IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref r0);
|
||||
|
||||
return new RawObjectMemoryManager<T>(array, offset, array.GetLength(1)).Memory;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
#if SPAN_RUNTIME_SUPPORT
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
|
||||
|
@ -12,7 +13,7 @@ using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
|
|||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="Array"/> type.
|
||||
|
@ -38,7 +39,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
#else
|
||||
IntPtr offset = RuntimeHelpers.GetArray3DDataByteOffset<T>();
|
||||
|
||||
return ref array.DangerousGetObjectDataReferenceAt<T>(offset);
|
||||
return ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -78,7 +79,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
((nint)(uint)i * (nint)(uint)height * (nint)(uint)width) +
|
||||
((nint)(uint)j * (nint)(uint)width) + (nint)(uint)k;
|
||||
IntPtr offset = RuntimeHelpers.GetArray3DDataByteOffset<T>();
|
||||
ref T r0 = ref array.DangerousGetObjectDataReferenceAt<T>(offset);
|
||||
ref T r0 = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, offset);
|
||||
ref T ri = ref Unsafe.Add(ref r0, index);
|
||||
|
||||
return ref ri;
|
||||
|
@ -212,7 +213,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
}
|
||||
|
||||
ref T r0 = ref array.DangerousGetReferenceAt(depth, 0, 0);
|
||||
IntPtr offset = array.DangerousGetObjectDataByteOffset(ref r0);
|
||||
IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref r0);
|
||||
int length = checked(array.GetLength(1) * array.GetLength(2));
|
||||
|
||||
return new RawObjectMemoryManager<T>(array, offset, length).Memory;
|
||||
|
|
|
@ -7,9 +7,8 @@ using System.IO;
|
|||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers;
|
||||
using Microsoft.Toolkit.HighPerformance.Streams;
|
||||
using Microsoft.Toolkit.HighPerformance.Streams.Sources;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="ArrayPoolBufferWriter{T}"/> type.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="ArrayPool{T}"/> type.
|
||||
|
|
|
@ -6,7 +6,7 @@ using System;
|
|||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="bool"/> type.
|
||||
|
@ -33,20 +33,6 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
return *(byte*)©
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given <see cref="bool"/> value into an <see cref="int"/>.
|
||||
/// </summary>
|
||||
/// <param name="flag">The input value to convert.</param>
|
||||
/// <returns>1 if <paramref name="flag"/> is <see langword="true"/>, 0 otherwise.</returns>
|
||||
/// <remarks>This method does not contain branching instructions.</remarks>
|
||||
[Pure]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[Obsolete("Use ToByte instead.")]
|
||||
public static unsafe int ToInt(this bool flag)
|
||||
{
|
||||
return *(byte*)&flag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given <see cref="bool"/> value to an <see cref="int"/> mask with
|
||||
/// all bits representing the value of the input flag (either 0xFFFFFFFF or 0x00000000).
|
||||
|
|
|
@ -8,7 +8,7 @@ using System;
|
|||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="HashCode"/> type.
|
||||
|
|
|
@ -10,9 +10,8 @@ using System.Runtime.CompilerServices;
|
|||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers;
|
||||
using Microsoft.Toolkit.HighPerformance.Streams;
|
||||
using Microsoft.Toolkit.HighPerformance.Streams.Sources;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="IBufferWriter{T}"/> type.
|
||||
|
|
|
@ -9,7 +9,7 @@ using System.IO;
|
|||
using System.Runtime.CompilerServices;
|
||||
using MemoryStream = Microsoft.Toolkit.HighPerformance.Streams.MemoryStream;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="IMemoryOwner{T}"/> type.
|
||||
|
|
|
@ -10,7 +10,7 @@ using System.Diagnostics.Contracts;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="List{T}"/> type.
|
||||
|
|
|
@ -9,7 +9,7 @@ using System.Runtime.CompilerServices;
|
|||
using System.Runtime.InteropServices;
|
||||
using MemoryStream = Microsoft.Toolkit.HighPerformance.Streams.MemoryStream;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="Memory{T}"/> type.
|
||||
|
|
|
@ -12,7 +12,7 @@ using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
|
|||
using Microsoft.Toolkit.HighPerformance.Buffers.Internals.Interfaces;
|
||||
using MemoryStream = Microsoft.Toolkit.HighPerformance.Streams.MemoryStream;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="ReadOnlyMemory{T}"/> type.
|
||||
|
|
|
@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
|
|||
using Microsoft.Toolkit.HighPerformance.Enumerables;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="ReadOnlySpan{T}"/> type.
|
||||
|
|
|
@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
|
|||
using Microsoft.Toolkit.HighPerformance.Enumerables;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="Span{T}"/> type.
|
||||
|
|
|
@ -6,7 +6,7 @@ using System.ComponentModel;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="SpinLock"/> type.
|
||||
|
|
|
@ -12,7 +12,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="Stream"/> type.
|
||||
|
|
|
@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
|
|||
using Microsoft.Toolkit.HighPerformance.Enumerables;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with the <see cref="string"/> type.
|
||||
|
|
|
@ -13,7 +13,6 @@ using System.Diagnostics.Contracts;
|
|||
using System.Reflection;
|
||||
#endif
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
|
||||
{
|
||||
|
@ -152,7 +151,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
|
|||
return (IntPtr)Unsafe.AsPointer(ref data);
|
||||
}
|
||||
|
||||
return obj.DangerousGetObjectDataByteOffset(ref data);
|
||||
return ObjectMarshal.DangerousGetObjectDataByteOffset(obj, ref data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -174,7 +173,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
|
|||
return ref Unsafe.AsRef<T>((void*)offset);
|
||||
}
|
||||
|
||||
return ref obj.DangerousGetObjectDataReferenceAt<T>(offset);
|
||||
return ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(obj, offset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -274,7 +273,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
|
|||
{
|
||||
var array = new T[1];
|
||||
|
||||
return array.DangerousGetObjectDataByteOffset(ref array[0]);
|
||||
return ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array[0]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -286,7 +285,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
|
|||
{
|
||||
var array = new T[1, 1];
|
||||
|
||||
return array.DangerousGetObjectDataByteOffset(ref array[0, 0]);
|
||||
return ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array[0, 0]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -298,7 +297,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
|
|||
{
|
||||
var array = new T[1, 1, 1];
|
||||
|
||||
return array.DangerousGetObjectDataByteOffset(ref array[0, 0, 0]);
|
||||
return ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array[0, 0, 0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using System;
|
|||
using System.Diagnostics.Contracts;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
|
||||
{
|
||||
|
|
|
@ -7,12 +7,12 @@ using System.Diagnostics.Contracts;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Extensions
|
||||
namespace Microsoft.Toolkit.HighPerformance.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with <see cref="object"/> instances.
|
||||
/// </summary>
|
||||
public static class ObjectExtensions
|
||||
public static class ObjectMarshal
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates the byte offset to a specific field within a given <see cref="object"/>.
|
||||
|
@ -29,7 +29,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
/// </remarks>
|
||||
[Pure]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static IntPtr DangerousGetObjectDataByteOffset<T>(this object obj, ref T data)
|
||||
public static IntPtr DangerousGetObjectDataByteOffset<T>(object obj, ref T data)
|
||||
{
|
||||
var rawObj = Unsafe.As<RawObjectData>(obj)!;
|
||||
ref byte r0 = ref rawObj.Data;
|
||||
|
@ -53,7 +53,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
/// </remarks>
|
||||
[Pure]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T DangerousGetObjectDataReferenceAt<T>(this object obj, IntPtr offset)
|
||||
public static ref T DangerousGetObjectDataReferenceAt<T>(object obj, IntPtr offset)
|
||||
{
|
||||
var rawObj = Unsafe.As<RawObjectData>(obj)!;
|
||||
ref byte r0 = ref rawObj.Data;
|
||||
|
@ -97,7 +97,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
/// <remarks>
|
||||
/// This extension behaves just like the following method:
|
||||
/// <code>
|
||||
/// public static bool TryUnbox<T>(this object obj, out T value)
|
||||
/// public static bool TryUnbox<T>(object obj, out T value)
|
||||
/// {
|
||||
/// if (obj is T)
|
||||
/// {
|
||||
|
@ -139,7 +139,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
|
|||
/// <exception cref="InvalidCastException">Thrown when <paramref name="obj"/> is not of type <typeparamref name="T"/>.</exception>
|
||||
[Pure]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T DangerousUnbox<T>(this object obj)
|
||||
public static ref T DangerousUnbox<T>(object obj)
|
||||
where T : struct
|
||||
{
|
||||
return ref Unsafe.Unbox<T>(obj);
|
|
@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
|
|||
#if SPAN_RUNTIME_SUPPORT
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Internals;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Views;
|
||||
using static Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
|
||||
|
@ -129,7 +129,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(offset));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(offset));
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.pitch = pitch;
|
||||
|
@ -222,7 +222,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(row, column));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, column));
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.pitch = columns - width;
|
||||
|
@ -250,7 +250,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(depth, 0, 0));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0));
|
||||
this.height = array.GetLength(1);
|
||||
this.width = array.GetLength(2);
|
||||
this.pitch = 0;
|
||||
|
@ -306,7 +306,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(depth, row, column));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, row, column));
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.pitch = columns - width;
|
||||
|
@ -465,7 +465,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
ref char r0 = ref text.DangerousGetReferenceAt(textStart + offset);
|
||||
|
||||
this.instance = text;
|
||||
this.offset = text.DangerousGetObjectDataByteOffset(ref r0);
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref r0);
|
||||
}
|
||||
else if (MemoryMarshal.TryGetArray(memory, out ArraySegment<T> segment))
|
||||
{
|
||||
|
@ -477,7 +477,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
T[] array = segment.Array!;
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(segment.Offset + offset));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(segment.Offset + offset));
|
||||
}
|
||||
else if (MemoryMarshal.TryGetMemoryManager<T, MemoryManager<T>>(memory, out var memoryManager, out int memoryManagerStart, out _))
|
||||
{
|
||||
|
@ -549,7 +549,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
|
||||
OverflowHelper.EnsureIsInNativeIntRange(height, width, pitch);
|
||||
|
||||
IntPtr offset = instance.DangerousGetObjectDataByteOffset(ref value);
|
||||
IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(instance, ref value);
|
||||
|
||||
return new Memory2D<T>(instance, offset, height, width, pitch);
|
||||
}
|
||||
|
@ -615,7 +615,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
else
|
||||
{
|
||||
ref T r0 = ref this.instance.DangerousGetObjectDataReferenceAt<T>(this.offset);
|
||||
ref T r0 = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(this.instance, this.offset);
|
||||
|
||||
return new Span2D<T>(ref r0, this.height, this.width, this.pitch);
|
||||
}
|
||||
|
@ -749,7 +749,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
|
||||
GCHandle handle = GCHandle.Alloc(this.instance, GCHandleType.Pinned);
|
||||
|
||||
void* pointer = Unsafe.AsPointer(ref this.instance.DangerousGetObjectDataReferenceAt<T>(this.offset));
|
||||
void* pointer = Unsafe.AsPointer(ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(this.instance, this.offset));
|
||||
|
||||
return new MemoryHandle(pointer, handle);
|
||||
}
|
||||
|
@ -775,7 +775,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
else if (typeof(T) == typeof(char) && this.instance.GetType() == typeof(string))
|
||||
{
|
||||
string text = Unsafe.As<string>(this.instance)!;
|
||||
int index = text.AsSpan().IndexOf(in text.DangerousGetObjectDataReferenceAt<char>(this.offset));
|
||||
int index = text.AsSpan().IndexOf(in ObjectMarshal.DangerousGetObjectDataReferenceAt<char>(text, this.offset));
|
||||
ReadOnlyMemory<char> temp = text.AsMemory(index, (int)Length);
|
||||
|
||||
// The string type could still be present if a user ends up creating a
|
||||
|
@ -795,7 +795,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
{
|
||||
// If it's a T[] array, also handle the initial offset
|
||||
T[] array = Unsafe.As<T[]>(this.instance)!;
|
||||
int index = array.AsSpan().IndexOf(ref array.DangerousGetObjectDataReferenceAt<T>(this.offset));
|
||||
int index = array.AsSpan().IndexOf(ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, this.offset));
|
||||
|
||||
memory = array.AsMemory(index, this.height * this.width);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
|
|||
#if SPAN_RUNTIME_SUPPORT
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Internals;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Views;
|
||||
using static Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
|
||||
|
@ -115,7 +115,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = text;
|
||||
this.offset = text.DangerousGetObjectDataByteOffset(ref text.DangerousGetReferenceAt(offset));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref text.DangerousGetReferenceAt(offset));
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.pitch = pitch;
|
||||
|
@ -182,7 +182,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(offset));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(offset));
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.pitch = pitch;
|
||||
|
@ -259,7 +259,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(row, column));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, column));
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.pitch = columns - width;
|
||||
|
@ -279,7 +279,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(depth, 0, 0));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0));
|
||||
this.height = array.GetLength(1);
|
||||
this.width = array.GetLength(2);
|
||||
this.pitch = 0;
|
||||
|
@ -327,7 +327,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
}
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(depth, row, column));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, row, column));
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.pitch = columns - width;
|
||||
|
@ -484,14 +484,14 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
ref char r0 = ref text.DangerousGetReferenceAt(textStart + offset);
|
||||
|
||||
this.instance = text;
|
||||
this.offset = text.DangerousGetObjectDataByteOffset(ref r0);
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref r0);
|
||||
}
|
||||
else if (MemoryMarshal.TryGetArray(memory, out ArraySegment<T> segment))
|
||||
{
|
||||
T[] array = segment.Array!;
|
||||
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(segment.Offset + offset));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(segment.Offset + offset));
|
||||
}
|
||||
else if (MemoryMarshal.TryGetMemoryManager<T, MemoryManager<T>>(memory, out var memoryManager, out int memoryManagerStart, out _))
|
||||
{
|
||||
|
@ -563,7 +563,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
|
||||
OverflowHelper.EnsureIsInNativeIntRange(height, width, pitch);
|
||||
|
||||
IntPtr offset = instance.DangerousGetObjectDataByteOffset(ref value);
|
||||
IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(instance, ref value);
|
||||
|
||||
return new ReadOnlyMemory2D<T>(instance, offset, height, width, pitch);
|
||||
}
|
||||
|
@ -630,7 +630,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
else
|
||||
{
|
||||
// This handles both arrays and strings
|
||||
ref T r0 = ref this.instance.DangerousGetObjectDataReferenceAt<T>(this.offset);
|
||||
ref T r0 = ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(this.instance, this.offset);
|
||||
|
||||
return new ReadOnlySpan2D<T>(in r0, this.height, this.width, this.pitch);
|
||||
}
|
||||
|
@ -764,7 +764,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
|
||||
GCHandle handle = GCHandle.Alloc(this.instance, GCHandleType.Pinned);
|
||||
|
||||
void* pointer = Unsafe.AsPointer(ref this.instance.DangerousGetObjectDataReferenceAt<T>(this.offset));
|
||||
void* pointer = Unsafe.AsPointer(ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(this.instance, this.offset));
|
||||
|
||||
return new MemoryHandle(pointer, handle);
|
||||
}
|
||||
|
@ -797,7 +797,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
// within the string), and the input reference, which we can get from the byte offset in use. The result
|
||||
// is the character index which we can use to create the final Memory<char> instance.
|
||||
string text = Unsafe.As<string>(this.instance)!;
|
||||
int index = text.AsSpan().IndexOf(in text.DangerousGetObjectDataReferenceAt<char>(this.offset));
|
||||
int index = text.AsSpan().IndexOf(in ObjectMarshal.DangerousGetObjectDataReferenceAt<char>(text, this.offset));
|
||||
ReadOnlyMemory<char> temp = text.AsMemory(index, (int)Length);
|
||||
|
||||
memory = Unsafe.As<ReadOnlyMemory<char>, ReadOnlyMemory<T>>(ref temp);
|
||||
|
@ -811,7 +811,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
{
|
||||
// If it's a T[] array, also handle the initial offset
|
||||
T[] array = Unsafe.As<T[]>(this.instance)!;
|
||||
int index = array.AsSpan().IndexOf(ref array.DangerousGetObjectDataReferenceAt<T>(this.offset));
|
||||
int index = array.AsSpan().IndexOf(ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, this.offset));
|
||||
|
||||
memory = array.AsMemory(index, this.height * this.width);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@ using System.Diagnostics;
|
|||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
#if !SPAN_RUNTIME_SUPPORT
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Internals;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Views;
|
||||
#if !SPAN_RUNTIME_SUPPORT
|
||||
|
@ -210,7 +212,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateReadOnlySpan(ref array.DangerousGetReferenceAt(offset), height);
|
||||
#else
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(offset));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(offset));
|
||||
this.height = height;
|
||||
#endif
|
||||
this.width = width;
|
||||
|
@ -234,7 +236,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateReadOnlySpan(ref array.DangerousGetReference(), array.GetLength(0));
|
||||
#else
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(0, 0));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(0, 0));
|
||||
this.height = array.GetLength(0);
|
||||
#endif
|
||||
this.width = this.stride = array.GetLength(1);
|
||||
|
@ -294,7 +296,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateReadOnlySpan(ref array.DangerousGetReferenceAt(row, column), height);
|
||||
#else
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(row, column));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, column));
|
||||
this.height = height;
|
||||
#endif
|
||||
this.width = width;
|
||||
|
@ -318,7 +320,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateReadOnlySpan(ref array.DangerousGetReferenceAt(depth, 0, 0), array.GetLength(1));
|
||||
#else
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(depth, 0, 0));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0));
|
||||
this.height = array.GetLength(1);
|
||||
#endif
|
||||
this.width = this.stride = array.GetLength(2);
|
||||
|
@ -369,7 +371,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateReadOnlySpan(ref array.DangerousGetReferenceAt(depth, row, column), height);
|
||||
#else
|
||||
this.instance = array;
|
||||
this.offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(depth, row, column));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, row, column));
|
||||
this.height = height;
|
||||
#endif
|
||||
this.width = width;
|
||||
|
|
|
@ -8,7 +8,9 @@ using System.Diagnostics;
|
|||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
#if !SPAN_RUNTIME_SUPPORT
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
#endif
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Internals;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory.Views;
|
||||
#if !SPAN_RUNTIME_SUPPORT
|
||||
|
@ -249,7 +251,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(offset), height);
|
||||
#else
|
||||
this.Instance = array;
|
||||
this.Offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(offset));
|
||||
this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(offset));
|
||||
this.height = height;
|
||||
#endif
|
||||
this.width = width;
|
||||
|
@ -281,7 +283,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReference(), array.GetLength(0));
|
||||
#else
|
||||
this.Instance = array;
|
||||
this.Offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(0, 0));
|
||||
this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(0, 0));
|
||||
this.height = array.GetLength(0);
|
||||
#endif
|
||||
this.width = this.Stride = array.GetLength(1);
|
||||
|
@ -349,7 +351,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(row, column), height);
|
||||
#else
|
||||
this.Instance = array;
|
||||
this.Offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(row, column));
|
||||
this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, column));
|
||||
this.height = height;
|
||||
#endif
|
||||
this.width = width;
|
||||
|
@ -381,7 +383,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(depth, 0, 0), array.GetLength(1));
|
||||
#else
|
||||
this.Instance = array;
|
||||
this.Offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(depth, 0, 0));
|
||||
this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0));
|
||||
this.height = array.GetLength(1);
|
||||
#endif
|
||||
this.width = this.Stride = array.GetLength(2);
|
||||
|
@ -440,7 +442,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
this.span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(depth, row, column), height);
|
||||
#else
|
||||
this.Instance = array;
|
||||
this.Offset = array.DangerousGetObjectDataByteOffset(ref array.DangerousGetReferenceAt(depth, row, column));
|
||||
this.Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, row, column));
|
||||
this.height = height;
|
||||
#endif
|
||||
this.width = width;
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Runtime.CompilerServices;
|
|||
#if SPAN_RUNTIME_SUPPORT
|
||||
using System.Runtime.InteropServices;
|
||||
#else
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
|
@ -98,7 +98,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
public ReadOnlyRef(object owner, in T value)
|
||||
{
|
||||
this.owner = owner;
|
||||
this.offset = owner.DangerousGetObjectDataByteOffset(ref Unsafe.AsRef(value));
|
||||
this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(owner, ref Unsafe.AsRef(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -107,7 +107,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
public ref readonly T Value
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref this.owner.DangerousGetObjectDataReferenceAt<T>(this.offset);
|
||||
get => ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(this.owner, this.offset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Runtime.CompilerServices;
|
|||
#if SPAN_RUNTIME_SUPPORT
|
||||
using System.Runtime.InteropServices;
|
||||
#else
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance.Helpers;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance
|
||||
|
@ -77,7 +77,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
public Ref(object owner, ref T value)
|
||||
{
|
||||
Owner = owner;
|
||||
Offset = owner.DangerousGetObjectDataByteOffset(ref value);
|
||||
Offset = ObjectMarshal.DangerousGetObjectDataByteOffset(owner, ref value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -86,7 +86,7 @@ namespace Microsoft.Toolkit.HighPerformance
|
|||
public ref T Value
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref Owner.DangerousGetObjectDataReferenceAt<T>(Offset);
|
||||
get => ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(Owner, Offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Buffers;
|
|||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Streams.Sources
|
||||
namespace Microsoft.Toolkit.HighPerformance.Streams
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IBufferWriter{T}"/> implementation wrapping an <see cref="ArrayPoolBufferWriter{T}"/> instance.
|
||||
|
|
|
@ -6,7 +6,6 @@ using System;
|
|||
using System.Runtime.CompilerServices;
|
||||
#if SPAN_RUNTIME_SUPPORT
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Streams
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Buffers;
|
|||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Buffers;
|
||||
|
||||
namespace Microsoft.Toolkit.HighPerformance.Streams.Sources
|
||||
namespace Microsoft.Toolkit.HighPerformance.Streams
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IBufferWriter{T}"/> implementation wrapping an <see cref="IBufferWriter{T}"/> instance.
|
||||
|
|
|
@ -26,6 +26,18 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
|
|||
/// </summary>
|
||||
private static readonly ConditionalWeakTable<Type, Action<object>> EntityValidatorMap = new();
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ConditionalWeakTable{TKey, TValue}"/> instance used to track display names for properties to validate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is necessary because we want to reuse the same <see cref="ValidationContext"/> instance for all validations, but
|
||||
/// with the same behavior with repsect to formatted names that new instances would have provided. The issue is that the
|
||||
/// <see cref="ValidationContext.DisplayName"/> property is not refreshed when we set <see cref="ValidationContext.MemberName"/>,
|
||||
/// so we need to replicate the same logic to retrieve the right display name for properties to validate and update that
|
||||
/// property manually right before passing the context to <see cref="Validator"/> and proceed with the normal functionality.
|
||||
/// </remarks>
|
||||
private static readonly ConditionalWeakTable<Type, Dictionary<string, string>> DisplayNamesMap = new();
|
||||
|
||||
/// <summary>
|
||||
/// The cached <see cref="PropertyChangedEventArgs"/> for <see cref="HasErrors"/>.
|
||||
/// </summary>
|
||||
|
@ -68,7 +80,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
|
|||
/// be used to validate all properties, which will reference the current instance.
|
||||
/// </summary>
|
||||
/// <param name="items">A set of key/value pairs to make available to consumers.</param>
|
||||
protected ObservableValidator(IDictionary<object, object?> items)
|
||||
protected ObservableValidator(IDictionary<object, object?>? items)
|
||||
{
|
||||
this.validationContext = new ValidationContext(this, items);
|
||||
}
|
||||
|
@ -80,7 +92,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
|
|||
/// </summary>
|
||||
/// <param name="serviceProvider">An <see cref="IServiceProvider"/> instance to make available during validation.</param>
|
||||
/// <param name="items">A set of key/value pairs to make available to consumers.</param>
|
||||
protected ObservableValidator(IServiceProvider serviceProvider, IDictionary<object, object?> items)
|
||||
protected ObservableValidator(IServiceProvider? serviceProvider, IDictionary<object, object?>? items)
|
||||
{
|
||||
this.validationContext = new ValidationContext(this, serviceProvider, items);
|
||||
}
|
||||
|
@ -541,6 +553,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
|
|||
|
||||
// Validate the property, by adding new errors to the existing list
|
||||
this.validationContext.MemberName = propertyName;
|
||||
this.validationContext.DisplayName = GetDisplayNameForProperty(propertyName!);
|
||||
|
||||
bool isValid = Validator.TryValidateProperty(value, this.validationContext, propertyErrors);
|
||||
|
||||
|
@ -611,6 +624,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
|
|||
|
||||
// Validate the property, by adding new errors to the local list
|
||||
this.validationContext.MemberName = propertyName;
|
||||
this.validationContext.DisplayName = GetDisplayNameForProperty(propertyName!);
|
||||
|
||||
bool isValid = Validator.TryValidateProperty(value, this.validationContext, localErrors);
|
||||
|
||||
|
@ -688,6 +702,36 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
|
|||
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display name for a given property. It could be a custom name or just the property name.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">The target property name being validated.</param>
|
||||
/// <returns>The display name for the property.</returns>
|
||||
private string GetDisplayNameForProperty(string propertyName)
|
||||
{
|
||||
static Dictionary<string, string> GetDisplayNames(Type type)
|
||||
{
|
||||
Dictionary<string, string> displayNames = new();
|
||||
|
||||
foreach (PropertyInfo property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
|
||||
{
|
||||
if (property.GetCustomAttribute<DisplayAttribute>() is DisplayAttribute attribute &&
|
||||
attribute.GetName() is string displayName)
|
||||
{
|
||||
displayNames.Add(property.Name, displayName);
|
||||
}
|
||||
}
|
||||
|
||||
return displayNames;
|
||||
}
|
||||
|
||||
// This method replicates the logic of DisplayName and GetDisplayName from the
|
||||
// ValidationContext class. See the original source in the BCL for more details.
|
||||
DisplayNamesMap.GetValue(GetType(), static t => GetDisplayNames(t)).TryGetValue(propertyName, out string? displayName);
|
||||
|
||||
return displayName ?? propertyName;
|
||||
}
|
||||
|
||||
#pragma warning disable SA1204
|
||||
/// <summary>
|
||||
/// Throws an <see cref="ArgumentNullException"/> when a property name given as input is <see langword="null"/>.
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace Microsoft.Toolkit.Mvvm.Messaging
|
|||
}
|
||||
|
||||
// Get or compute the registration methods for the current recipient type.
|
||||
// As in Microsoft.Toolkit.Extensions.TypeExtensions.ToTypeString, we use a lambda
|
||||
// As in Microsoft.Toolkit.Diagnostics.TypeExtensions.ToTypeString, we use a lambda
|
||||
// expression instead of a method group expression to leverage the statically initialized
|
||||
// delegate and avoid repeated allocations for each invocation of this method.
|
||||
// For more info on this, see the related issue at https://github.com/dotnet/roslyn/issues/5835.
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Title>Windows Community Toolkit .NET Standard Parsers</Title>
|
||||
<Description>
|
||||
This .NET standard library contains various parsers
|
||||
|
||||
Markdown: Allows you to parse a Markdown String into a Markdown Document, and then Render it with a Markdown Renderer.
|
||||
|
||||
</Description>
|
||||
<PackageTags>UWP Toolkit Windows Parsers Parsing Markdown</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Toolkit\Microsoft.Toolkit.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,27 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// AuthenticationResult class, parameters: ResponseErrorDetail(uint), ResponseData(string) and ResponseStatus(AuthenticationResultStatus)
|
||||
/// </summary>
|
||||
public class AuthenticationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication error detail
|
||||
/// </summary>
|
||||
public uint ResponseErrorDetail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication result data
|
||||
/// </summary>
|
||||
public string ResponseData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication status, could be UserCancel, ErrorHttp and Success.
|
||||
/// </summary>
|
||||
public AuthenticationResultStatus ResponseStatus { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the status of the authentication operation
|
||||
/// </summary>
|
||||
public enum AuthenticationResultStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The operation succeeded, and the response data is available.
|
||||
/// </summary>
|
||||
Success,
|
||||
|
||||
/// <summary>
|
||||
/// The operation was canceled by the user
|
||||
/// </summary>
|
||||
UserCancel,
|
||||
|
||||
/// <summary>
|
||||
/// The operation failed because a specific HTTP error was returned, for example 404
|
||||
/// </summary>
|
||||
ErrorHttp
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for data providers in this library.
|
||||
/// </summary>
|
||||
/// <typeparam name="TConfig">Query configuration type for given provider.</typeparam>
|
||||
public abstract class DataProviderBase<TConfig>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataProviderBase{TConfig}"/> class.
|
||||
/// </summary>
|
||||
public DataProviderBase()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load data from provider endpoint.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSchema">Strong typed object to parse the response items into.</typeparam>
|
||||
/// <param name="config">Query configuration.</param>
|
||||
/// <param name="maxRecords">Upper record limit.</param>
|
||||
/// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
|
||||
/// <param name="parser">Parser to use for results.</param>
|
||||
/// <returns>Strong typed list of results.</returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method, so nesting generic types is necessary.")]
|
||||
public async Task<IEnumerable<TSchema>> LoadDataAsync<TSchema>(TConfig config, int maxRecords, int pageIndex, Parsers.IParser<TSchema> parser)
|
||||
where TSchema : Parsers.SchemaBase
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
throw new ConfigNullException();
|
||||
}
|
||||
|
||||
if (parser == null)
|
||||
{
|
||||
throw new ParserNullException();
|
||||
}
|
||||
|
||||
ValidateConfig(config);
|
||||
|
||||
var result = await GetDataAsync(config, maxRecords, pageIndex, parser);
|
||||
if (result != null)
|
||||
{
|
||||
return result
|
||||
.Take(maxRecords)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return Array.Empty<TSchema>();
|
||||
}
|
||||
|
||||
private static HttpClient httpClient;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets static instance of HttpClient.
|
||||
/// </summary>
|
||||
public static HttpClient HttpClient
|
||||
{
|
||||
get { return httpClient ?? (httpClient = new HttpClient()); }
|
||||
set { httpClient = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Derived classes will have to implement this method to return provider data
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration to use</param>
|
||||
/// <param name="maxRecords">Maximum number of records to return</param>
|
||||
/// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
|
||||
/// <param name="parser">Parser to use</param>
|
||||
/// <typeparam name="TSchema">Schema defining data returned</typeparam>
|
||||
/// <returns>List of data</returns>
|
||||
protected abstract Task<IEnumerable<TSchema>> GetDataAsync<TSchema>(TConfig config, int maxRecords, int pageIndex, Parsers.IParser<TSchema> parser)
|
||||
where TSchema : Parsers.SchemaBase;
|
||||
|
||||
/// <summary>
|
||||
/// Method provided by derived class to validate specified configuration
|
||||
/// </summary>
|
||||
/// <param name="config">Configuration to validate</param>
|
||||
protected abstract void ValidateConfig(TConfig config);
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for data providers in this library.
|
||||
/// </summary>
|
||||
/// <typeparam name="TConfig">Strong typed query configuration object.</typeparam>
|
||||
/// <typeparam name="TSchema">Strong typed object to parse the response items into.</typeparam>
|
||||
public abstract class DataProviderBase<TConfig, TSchema> : DataProviderBase<TConfig>
|
||||
where TSchema : Parsers.SchemaBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Load data from provider endpoint.
|
||||
/// </summary>
|
||||
/// <param name="config">Query configuration.</param>
|
||||
/// <param name="maxRecords">Upper record limit.</param>
|
||||
/// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
|
||||
/// <returns>List of strong typed objects.</returns>
|
||||
public Task<IEnumerable<TSchema>> LoadDataAsync(TConfig config, int maxRecords = 20, int pageIndex = 0)
|
||||
{
|
||||
return LoadDataAsync(config, maxRecords, pageIndex, GetDefaultParser(config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default parser abstract method.
|
||||
/// </summary>
|
||||
/// <param name="config">Query configuration object.</param>
|
||||
/// <returns>Strong typed default parser.</returns>
|
||||
protected abstract Parsers.IParser<TSchema> GetDefaultParser(TConfig config);
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// This class offers general purpose methods.
|
||||
/// </summary>
|
||||
internal static class ExtensionMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts between enumeration value and string value.
|
||||
/// </summary>
|
||||
/// <param name="value">Enumeration.</param>
|
||||
/// <returns>Returns string value.</returns>
|
||||
private static string GetStringValue(Enum value)
|
||||
{
|
||||
string output = null;
|
||||
Type type = value.GetType();
|
||||
|
||||
FieldInfo fi = type.GetRuntimeField(value.ToString());
|
||||
Parsers.Core.StringValueAttribute[] attrs = fi.GetCustomAttributes(typeof(Parsers.Core.StringValueAttribute), false) as Parsers.Core.StringValueAttribute[];
|
||||
if (attrs != null && attrs.Length > 0)
|
||||
{
|
||||
output = attrs[0].Value;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// This gets an Uri value.
|
||||
/// </summary>
|
||||
public interface IAuthenticationBroker
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the authentication status, it could be UserCancel, ErrorHttp and Success.
|
||||
/// </summary>
|
||||
/// <param name="requestUri"> Authorization base url</param>
|
||||
/// <param name="callbackUri"> LinkedInOAuthTokens callbackUri</param>
|
||||
/// <returns> Returns a status </returns>
|
||||
Task<AuthenticationResult> Authenticate(Uri requestUri, Uri callbackUri);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic interface that all deployed service providers implement.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Reference to underlying data service provider.</typeparam>
|
||||
/// <typeparam name="U">Strongly-typed schema for data returned in list query.</typeparam>
|
||||
/// <typeparam name="V">Configuration type specifying query parameters.</typeparam>
|
||||
public interface IDataService<T, U, V>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the underlying data service provider.
|
||||
/// </summary>
|
||||
T Provider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Makes a request for a list of data from the given service provider.
|
||||
/// </summary>
|
||||
/// <param name="config">Describes the query on the list data request.</param>
|
||||
/// <param name="maxRecords">Specifies an upper limit to the number of records returned.</param>
|
||||
/// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
|
||||
/// <returns>Returns a strongly typed list of results from the service.</returns>
|
||||
Task<List<U>> RequestAsync(V config, int maxRecords, int pageIndex = 0);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface gets a PasswordCredential, store the credential and remove the key.
|
||||
/// </summary>
|
||||
public interface IPasswordManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the user credentials.
|
||||
/// </summary>
|
||||
/// <param name="key"> Receive the storage key user and the access token </param>
|
||||
/// <returns> Returns user credential.</returns>
|
||||
PasswordCredential Get(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Store users credential.
|
||||
/// </summary>
|
||||
/// <param name="resource"> Resource</param>
|
||||
/// <param name="credential"> Username and password.</param>
|
||||
void Store(string resource, PasswordCredential credential);
|
||||
|
||||
/// <summary>
|
||||
/// Remove users credential.
|
||||
/// </summary>
|
||||
/// <param name="key"> Credential unique key</param>
|
||||
void Remove(string key);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides platform specific logic to sign request for OAuth communication
|
||||
/// </summary>
|
||||
public interface ISignatureManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Generate request signature
|
||||
/// </summary>
|
||||
/// <param name="baseString">String to sign</param>
|
||||
/// <param name="secret">Secret to use to sign</param>
|
||||
/// <param name="append">If true append & to the base string</param>
|
||||
/// <returns>The signed baseString to use in the OAuth requests</returns>
|
||||
string GetSignature(string baseString, string secret, bool append = false);
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface store the key value
|
||||
/// </summary>
|
||||
public interface IStorageManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the key value
|
||||
/// </summary>
|
||||
/// <param name="key"> Token value </param>
|
||||
/// <returns> Returns a string value</returns>
|
||||
Task<string> GetAsync(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the key value
|
||||
/// </summary>
|
||||
/// <param name="key"> Token key </param>
|
||||
/// <param name="value"> String value </param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task SetAsync(string key, string value);
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// PasswordCredential class composed of UserName and Password, both strings.
|
||||
/// </summary>
|
||||
public class PasswordCredential
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the username from login form
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the password from login form
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception for null Config.
|
||||
/// </summary>
|
||||
public class ConfigNullException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigNullException"/> class.
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public ConfigNullException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigNullException"/> class.
|
||||
/// Constructor accepting additional message string.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional error information.</param>
|
||||
public ConfigNullException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigNullException"/> class.
|
||||
/// Constructor accepting additional message string and inner exception
|
||||
/// </summary>
|
||||
/// <param name="message">Additional error information.</param>
|
||||
/// <param name="innerException">Reference to inner exception.</param>
|
||||
public ConfigNullException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception for config parameter being null.
|
||||
/// </summary>
|
||||
public class ConfigParameterNullException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigParameterNullException"/> class.
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public ConfigParameterNullException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigParameterNullException"/> class.
|
||||
/// Accepts parameter name.
|
||||
/// </summary>
|
||||
/// <param name="parameter">Name of the parameter.</param>
|
||||
public ConfigParameterNullException(string parameter)
|
||||
: base(string.Format("The parameter '{0}' in config is null.", parameter))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigParameterNullException"/> class.
|
||||
/// Accepts parameter name and inner exception.
|
||||
/// </summary>
|
||||
/// <param name="message">Name of the parameter.</param>
|
||||
/// <param name="innerException">Reference to the inner exception.</param>
|
||||
public ConfigParameterNullException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception for no OAuth keys being present.
|
||||
/// </summary>
|
||||
public class OAuthKeysNotPresentException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OAuthKeysNotPresentException"/> class.
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public OAuthKeysNotPresentException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OAuthKeysNotPresentException"/> class.
|
||||
/// Constructor with information on missing key.
|
||||
/// </summary>
|
||||
/// <param name="key">Name of the missing key.</param>
|
||||
public OAuthKeysNotPresentException(string key)
|
||||
: base(string.Format("Open Authentication Key '{0}' not present", key))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OAuthKeysNotPresentException"/> class.
|
||||
/// Constructor with additional message and inner exception.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional exception message.</param>
|
||||
/// <param name="innerException">Reference to inner exception.</param>
|
||||
public OAuthKeysNotPresentException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception for revoked OAuth keys.
|
||||
/// </summary>
|
||||
public class OAuthKeysRevokedException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OAuthKeysRevokedException"/> class.
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public OAuthKeysRevokedException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OAuthKeysRevokedException"/> class.
|
||||
/// Constructor with additional message.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional message</param>
|
||||
public OAuthKeysRevokedException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OAuthKeysRevokedException"/> class.
|
||||
/// Constructor with additional message and inner exception.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional message.</param>
|
||||
/// <param name="innerException">Reference to inner exception.</param>
|
||||
public OAuthKeysRevokedException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception for null Parser.
|
||||
/// </summary>
|
||||
public class ParserNullException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ParserNullException"/> class.
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public ParserNullException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ParserNullException"/> class.
|
||||
/// Constructor with additional message.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional message</param>
|
||||
public ParserNullException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ParserNullException"/> class.
|
||||
/// Constructor with additional message and inner exception.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional message.</param>
|
||||
/// <param name="innerException">Reference to inner exception.</param>
|
||||
public ParserNullException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception for failed requests.
|
||||
/// </summary>
|
||||
public class RequestFailedException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestFailedException"/> class.
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public RequestFailedException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestFailedException"/> class.
|
||||
/// Constructor with additional message.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional message.</param>
|
||||
public RequestFailedException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestFailedException"/> class.
|
||||
/// Constructor with status code and reason for request failure.
|
||||
/// </summary>
|
||||
/// <param name="statusCode">Failure status code.</param>
|
||||
/// <param name="reason">Failure reason.</param>
|
||||
public RequestFailedException(HttpStatusCode statusCode, string reason)
|
||||
: base(string.Format("Request failed with status code {0} and reason '{1}'", (int)statusCode, reason))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestFailedException"/> class.
|
||||
/// Constructor with additional message and inner exception.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional message.</param>
|
||||
/// <param name="innerException">Reference to inner exception.</param>
|
||||
public RequestFailedException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception for too many requests.
|
||||
/// </summary>
|
||||
public class TooManyRequestsException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TooManyRequestsException"/> class.
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public TooManyRequestsException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TooManyRequestsException"/> class.
|
||||
/// Constructor with additional message.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional message.</param>
|
||||
public TooManyRequestsException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TooManyRequestsException"/> class.
|
||||
/// Constructor with additional message and reference to inner exception.
|
||||
/// </summary>
|
||||
/// <param name="message">Additional message.</param>
|
||||
/// <param name="innerException">Reference to inner exception.</param>
|
||||
public TooManyRequestsException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Toolkit.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception for user not found.
|
||||
/// </summary>
|
||||
public class UserNotFoundException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserNotFoundException"/> class.
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public UserNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserNotFoundException"/> class.
|
||||
/// Constructor with screen/user name information.
|
||||
/// </summary>
|
||||
/// <param name="screenName">Name of user not found.</param>
|
||||
public UserNotFoundException(string screenName)
|
||||
: base("User " + screenName + " not found.")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserNotFoundException"/> class.
|
||||
/// Constructor with screen/user name information and inner exception.
|
||||
/// </summary>
|
||||
/// <param name="screenName">Name of user not found.</param>
|
||||
/// <param name="innerException">Reference to inner exception.</param>
|
||||
public UserNotFoundException(string screenName, Exception innerException)
|
||||
: base("User " + screenName + " not found.", innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>uap10.0.17763;netstandard2.0;NET462</TargetFrameworks>
|
||||
<Title>Windows Community Toolkit .NET Standard Services</Title>
|
||||
<Description>
|
||||
This .NET standard library enables access to different data sources such as Microsoft Graph, OneDrive, Twitter, Microsoft Translator, and LinkedIn. It is part of the Windows Community Toolkit.
|
||||
</Description>
|
||||
<PackageTags>UWP Community Toolkit Windows Microsoft Graph OneDrive Twitter Translator LinkedIn service login OAuth</PackageTags>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<NoWarn>CS8002;CS0618</NoWarn>
|
||||
<DeterministicSourcePaths Condition="'$(EnableSourceLink)' == ''">false</DeterministicSourcePaths>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0.17763'">
|
||||
<DefineConstants Condition="'$(DisableImplicitFrameworkDefines)' != 'true'">$(DefineConstants);WINRT</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net462'">
|
||||
<UseWpf>true</UseWpf>
|
||||
<EnableDefaultPageItems>false</EnableDefaultPageItems>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Toolkit.Parsers\Microsoft.Toolkit.Parsers.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Toolkit\Microsoft.Toolkit.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Text.Json" Version="4.7.2" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='uap10.0.17763'">
|
||||
<ProjectReference Include="..\Microsoft.Toolkit.Uwp\Microsoft.Toolkit.Uwp.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="!('$(TargetFramework)'=='net462')">
|
||||
<Compile Remove="PlatformSpecific\NetFramework\**\*" />
|
||||
<None Remove="PlatformSpecific\NetFramework\**\*" />
|
||||
<Page Remove="PlatformSpecific\NetFramework\**\*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net462'">
|
||||
<Reference Include="System.Web" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Wpf.UI.Controls.WebView" Version="[5.0.0-preview.gb86cb1c4cb,)" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Forms.UI.Controls.WebView" Version="[5.0.0-preview.gb86cb1c4cb,)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="!('$(TargetFramework)'=='uap10.0.17763')">
|
||||
<Compile Remove="PlatformSpecific\Uwp\**\*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,78 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
#if WINRT
|
||||
using Windows.Security.Cryptography;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
#endif
|
||||
namespace Microsoft.Toolkit.Services.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth Encoder.
|
||||
/// </summary>
|
||||
internal static class OAuthEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Url encode input string.
|
||||
/// </summary>
|
||||
/// <param name="value">Input string.</param>
|
||||
/// <returns>Encoded string.</returns>
|
||||
public static string UrlEncode(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var result = Uri.EscapeDataString(value);
|
||||
|
||||
// UrlEncode escapes with lowercase characters (e.g. %2f) but oAuth needs %2F
|
||||
result = Regex.Replace(result, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper());
|
||||
|
||||
// these characters are not escaped by UrlEncode() but needed to be escaped
|
||||
result = result
|
||||
.Replace("(", "%28")
|
||||
.Replace(")", "%29")
|
||||
.Replace("$", "%24")
|
||||
.Replace("!", "%21")
|
||||
.Replace("*", "%2A")
|
||||
.Replace("'", "%27");
|
||||
|
||||
// these characters are escaped by UrlEncode() but will fail if unescaped!
|
||||
result = result.Replace("%7E", "~");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode list of parameters.
|
||||
/// </summary>
|
||||
/// <param name="parameters">List of parameters.</param>
|
||||
/// <returns>Encoded string of parameters.</returns>
|
||||
public static string UrlEncode(IEnumerable<OAuthParameter> parameters)
|
||||
{
|
||||
string rawUrl = string.Join("&", parameters.OrderBy(p => p.Key).Select(p => p.ToString()).ToArray());
|
||||
return UrlEncode(rawUrl);
|
||||
}
|
||||
|
||||
#if WINRT
|
||||
public static string GenerateHash(string input, string key)
|
||||
{
|
||||
MacAlgorithmProvider mac = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha1);
|
||||
IBuffer keyMaterial = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8);
|
||||
CryptographicKey cryptoKey = mac.CreateKey(keyMaterial);
|
||||
IBuffer hash = CryptographicEngine.Sign(cryptoKey, CryptographicBuffer.ConvertStringToBinary(input, BinaryStringEncoding.Utf8));
|
||||
return CryptographicBuffer.EncodeToBase64String(hash);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth parameter.
|
||||
/// </summary>
|
||||
internal class OAuthParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets key property.
|
||||
/// </summary>
|
||||
public string Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets value property.
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OAuthParameter"/> class.
|
||||
/// Constructor accepting key and value.
|
||||
/// </summary>
|
||||
/// <param name="key">Key.</param>
|
||||
/// <param name="value">Value.</param>
|
||||
public OAuthParameter(string key, string value)
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ToString override.
|
||||
/// </summary>
|
||||
/// <returns>String representation</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return ToString(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format key / value into string.
|
||||
/// </summary>
|
||||
/// <param name="withQuotes">Whether to create quotes in string.</param>
|
||||
/// <returns>Formatted string of key / value.</returns>
|
||||
public string ToString(bool withQuotes)
|
||||
{
|
||||
string format;
|
||||
if (withQuotes)
|
||||
{
|
||||
format = "{0}=\"{1}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
format = "{0}={1}";
|
||||
}
|
||||
|
||||
return string.Format(CultureInfo.InvariantCulture, format, OAuthEncoder.UrlEncode(Key), OAuthEncoder.UrlEncode(Value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth Uri extensions.
|
||||
/// </summary>
|
||||
internal static class OAuthUriExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Get query parameters from Uri.
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri to process.</param>
|
||||
/// <returns>Dictionary of query parameters.</returns>
|
||||
public static IDictionary<string, string> GetQueryParams(this Uri uri)
|
||||
{
|
||||
var dict = uri.Query.Remove(0, 1).Split('&').ToDictionary(c => c.Split('=')[0], c => Uri.UnescapeDataString(c.Split('=')[1]));
|
||||
return dict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get absolute Uri.
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri to process.</param>
|
||||
/// <returns>Uri without query string.</returns>
|
||||
public static string AbsoluteWithoutQuery(this Uri uri)
|
||||
{
|
||||
if (string.IsNullOrEmpty(uri.Query))
|
||||
{
|
||||
return uri.AbsoluteUri;
|
||||
}
|
||||
|
||||
return uri.AbsoluteUri.Replace(uri.Query, string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalize the Uri into string.
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri to process.</param>
|
||||
/// <returns>Normalized string.</returns>
|
||||
public static string Normalize(this Uri uri)
|
||||
{
|
||||
var result = new StringBuilder(string.Format(CultureInfo.InvariantCulture, "{0}://{1}", uri.Scheme, uri.Host));
|
||||
if (!((uri.Scheme == "http" && uri.Port == 80) || (uri.Scheme == "https" && uri.Port == 443)))
|
||||
{
|
||||
result.Append(string.Concat(":", uri.Port));
|
||||
}
|
||||
|
||||
result.Append(uri.AbsolutePath);
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
using ApplicationForm = System.Windows.Forms.Application;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.NetFramework
|
||||
{
|
||||
internal class NetFrameworkAuthenticationBroker : IAuthenticationBroker
|
||||
{
|
||||
public Task<AuthenticationResult> Authenticate(Uri requestUri, Uri callbackUri)
|
||||
{
|
||||
int numberForms = ApplicationForm.OpenForms.Count;
|
||||
if (numberForms > 0)
|
||||
{
|
||||
return this.AuthenticateForm(requestUri, callbackUri);
|
||||
}
|
||||
else if (Application.Current != null)
|
||||
{
|
||||
return this.AuthenticateWindow(requestUri, callbackUri);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Your code shouldn't reach this exception.
|
||||
throw new Exception("Cannot identify the current application. Please review your main app");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<AuthenticationResult> AuthenticateWindow(Uri requestUri, Uri callbackUri)
|
||||
{
|
||||
PopupWPF popupWindow;
|
||||
var taskCompletionSource = new TaskCompletionSource<AuthenticationResult>();
|
||||
popupWindow = new PopupWPF(callbackUri);
|
||||
popupWindow.Closed += (sender, e) =>
|
||||
{
|
||||
taskCompletionSource.SetResult(HandleExit(popupWindow.ActualUrl));
|
||||
};
|
||||
|
||||
popupWindow.Show();
|
||||
popupWindow.NavigateTo(requestUri.AbsoluteUri);
|
||||
return await taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
public async Task<AuthenticationResult> AuthenticateForm(Uri requestUri, Uri callbackUri)
|
||||
{
|
||||
PopupForm popupForm;
|
||||
var taskCompletionSource = new TaskCompletionSource<AuthenticationResult>();
|
||||
popupForm = new PopupForm(callbackUri);
|
||||
popupForm.FormClosed += (sender, e) =>
|
||||
{
|
||||
taskCompletionSource.SetResult(HandleExit(popupForm.ActualUrl));
|
||||
};
|
||||
|
||||
popupForm.Show();
|
||||
popupForm.NavigateTo(requestUri.AbsoluteUri);
|
||||
return await taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
private AuthenticationResult HandleExit(Uri actualUrl)
|
||||
{
|
||||
var result = new AuthenticationResult();
|
||||
if (actualUrl != null)
|
||||
{
|
||||
var query = System.Web.HttpUtility.ParseQueryString(actualUrl.Query);
|
||||
|
||||
result.ResponseData = query.ToString();
|
||||
result.ResponseStatus = AuthenticationResultStatus.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.ResponseStatus = AuthenticationResultStatus.ErrorHttp;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
using static Microsoft.Toolkit.Services.PlatformSpecific.NetFramework.PasswordManagerNativeMethods;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.NetFramework
|
||||
{
|
||||
internal class NetFrameworkPasswordManager : IPasswordManager
|
||||
{
|
||||
public void Store(string resource, PasswordCredential credential)
|
||||
{
|
||||
// Validations.
|
||||
byte[] byteArray = Encoding.Unicode.GetBytes(credential.Password);
|
||||
|
||||
// Go ahead with what we have are stuff it into the CredMan structures.
|
||||
Credential cred = new Credential
|
||||
{
|
||||
TargetName = resource,
|
||||
UserName = credential.UserName,
|
||||
CredentialBlob = credential.Password,
|
||||
CredentialBlobSize = (uint)byteArray.Length,
|
||||
AttributeCount = 0,
|
||||
Attributes = IntPtr.Zero,
|
||||
Comment = null,
|
||||
TargetAlias = null,
|
||||
Type = CRED_TYPE.GENERIC,
|
||||
Persist = CRED_PERSIST.LOCAL_MACHINE
|
||||
};
|
||||
NativeCredential userCredential = NativeCredential.GetNativeCredential(cred);
|
||||
|
||||
// Write the info into the CredMan storage.
|
||||
bool written = CredWrite(ref userCredential, 0);
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
if (!written)
|
||||
{
|
||||
string message = "CredWrite failed with the error code " + lastError.ToString();
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
}
|
||||
|
||||
public PasswordCredential Get(string key)
|
||||
{
|
||||
int lastError = Marshal.GetHRForLastWin32Error();
|
||||
|
||||
if (!CredRead(key, CRED_TYPE.GENERIC, 0, out var nCredPtr))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
CriticalCredentialHandle credentialHandle = new CriticalCredentialHandle(nCredPtr);
|
||||
|
||||
Credential credential = credentialHandle.GetCredential();
|
||||
return new PasswordCredential
|
||||
{
|
||||
UserName = credential.UserName,
|
||||
Password = credential.CredentialBlob
|
||||
};
|
||||
}
|
||||
|
||||
public void Remove(string key)
|
||||
{
|
||||
CredDelete(key, CRED_TYPE.GENERIC, 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.NetFramework
|
||||
{
|
||||
internal class NetFrameworkSignatureManager : ISignatureManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Generate request signature.
|
||||
/// </summary>
|
||||
/// <param name="baseString">String to sign</param>
|
||||
/// <param name="secret">Secret to use to sign</param>
|
||||
/// <param name="append">If true append & to the base string</param>
|
||||
/// <returns>Signature.</returns>
|
||||
public string GetSignature(string baseString, string secret, bool append = false)
|
||||
{
|
||||
var key = append ? secret + "&" : secret;
|
||||
|
||||
var baseStringByte = Encoding.UTF8.GetBytes(baseString);
|
||||
var keyByte = Encoding.UTF8.GetBytes(key);
|
||||
|
||||
using (HMACSHA1 hmac = new HMACSHA1(keyByte))
|
||||
{
|
||||
hmac.Initialize();
|
||||
var hash = hmac.ComputeHash(baseStringByte);
|
||||
string base64 = Convert.ToBase64String(hash);
|
||||
return base64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.IsolatedStorage;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.NetFramework
|
||||
{
|
||||
internal class NetFrameworkStorageManager : IStorageManager
|
||||
{
|
||||
private const string FileName = "credential_service_data.txt";
|
||||
private const char Separator = ':';
|
||||
|
||||
public async Task<string> GetAsync(string key)
|
||||
{
|
||||
var isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);
|
||||
|
||||
using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream(FileName, FileMode.OpenOrCreate, isoStore))
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(isoStream))
|
||||
{
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
var line = (await reader.ReadLineAsync()).Split(Separator);
|
||||
var currentKey = line.First();
|
||||
if (currentKey == key)
|
||||
{
|
||||
return line.Last();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task SetAsync(string key, string value)
|
||||
{
|
||||
var isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);
|
||||
|
||||
using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream(FileName, FileMode.Append, isoStore))
|
||||
{
|
||||
using (StreamWriter writer = new StreamWriter(isoStream))
|
||||
{
|
||||
return writer.WriteLineAsync(string.Concat(key, Separator, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.NetFramework
|
||||
{
|
||||
internal class PasswordManagerNativeMethods
|
||||
{
|
||||
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, out IntPtr credentialPtr);
|
||||
|
||||
[DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
internal static extern bool CredWrite([In] ref NativeCredential userCredential, [In] uint flags);
|
||||
|
||||
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
|
||||
internal static extern bool CredFree([In] IntPtr cred);
|
||||
|
||||
[DllImport("advapi32.dll", EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode)]
|
||||
internal static extern bool CredDelete(string target, CRED_TYPE type, int flags);
|
||||
|
||||
internal enum CRED_TYPE : uint
|
||||
{
|
||||
GENERIC = 1,
|
||||
DOMAIN_PASSWORD = 2,
|
||||
DOMAIN_CERTIFICATE = 3,
|
||||
DOMAIN_VISIBLE_PASSWORD = 4,
|
||||
GENERIC_CERTIFICATE = 5,
|
||||
DOMAIN_EXTENDED = 6,
|
||||
MAXIMUM = 7, // Maximum supported cred type
|
||||
MAXIMUM_EX = MAXIMUM + 1000, // Allow new applications to run on old OSes
|
||||
}
|
||||
|
||||
internal enum CRED_PERSIST : uint
|
||||
{
|
||||
SESSION = 1,
|
||||
LOCAL_MACHINE = 2,
|
||||
ENTERPRISE = 3,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct NativeCredential
|
||||
{
|
||||
internal uint Flags;
|
||||
internal CRED_TYPE Type;
|
||||
internal IntPtr TargetName;
|
||||
internal IntPtr Comment;
|
||||
internal System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
|
||||
internal uint CredentialBlobSize;
|
||||
internal IntPtr CredentialBlob;
|
||||
internal uint Persist;
|
||||
internal uint AttributeCount;
|
||||
internal IntPtr Attributes;
|
||||
internal IntPtr TargetAlias;
|
||||
internal IntPtr UserName;
|
||||
|
||||
/// <summary>
|
||||
/// This method derives a NativeCredential instance from a given Credential instance.
|
||||
/// </summary>
|
||||
/// <param name="cred">The managed Credential counterpart containing data to be stored.</param>
|
||||
/// <returns>A NativeCredential instance that is derived from the given Credential
|
||||
/// instance.</returns>
|
||||
internal static NativeCredential GetNativeCredential(Credential cred)
|
||||
{
|
||||
return new NativeCredential
|
||||
{
|
||||
AttributeCount = 0,
|
||||
Attributes = IntPtr.Zero,
|
||||
Comment = IntPtr.Zero,
|
||||
TargetAlias = IntPtr.Zero,
|
||||
Type = CRED_TYPE.GENERIC,
|
||||
Persist = (uint)cred.Persist,
|
||||
CredentialBlobSize = (uint)cred.CredentialBlobSize,
|
||||
TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName),
|
||||
CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob),
|
||||
UserName = Marshal.StringToCoTaskMemUni(cred.UserName)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct Credential
|
||||
{
|
||||
internal uint Flags;
|
||||
internal CRED_TYPE Type;
|
||||
internal string TargetName;
|
||||
internal string Comment;
|
||||
internal System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
|
||||
internal uint CredentialBlobSize;
|
||||
internal string CredentialBlob;
|
||||
internal CRED_PERSIST Persist;
|
||||
internal uint AttributeCount;
|
||||
internal IntPtr Attributes;
|
||||
internal string TargetAlias;
|
||||
internal string UserName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle and create the credential.
|
||||
/// </summary>
|
||||
internal sealed class CriticalCredentialHandle : CriticalHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
// Set the handle.
|
||||
internal CriticalCredentialHandle(IntPtr preexistingHandle)
|
||||
{
|
||||
SetHandle(preexistingHandle);
|
||||
}
|
||||
|
||||
internal Credential GetCredential()
|
||||
{
|
||||
if (!IsInvalid)
|
||||
{
|
||||
// Get the Credential from the mem location
|
||||
NativeCredential nativeCredential = (NativeCredential)Marshal.PtrToStructure(handle, typeof(NativeCredential));
|
||||
|
||||
// Create a managed Credential type and fill it with data from the native counterpart.
|
||||
return new Credential
|
||||
{
|
||||
CredentialBlobSize = nativeCredential.CredentialBlobSize,
|
||||
CredentialBlob = Marshal.PtrToStringUni(nativeCredential.CredentialBlob, (int)nativeCredential.CredentialBlobSize / 2),
|
||||
UserName = Marshal.PtrToStringUni(nativeCredential.UserName),
|
||||
TargetName = Marshal.PtrToStringUni(nativeCredential.TargetName),
|
||||
TargetAlias = Marshal.PtrToStringUni(nativeCredential.TargetAlias),
|
||||
Type = nativeCredential.Type,
|
||||
Flags = nativeCredential.Flags,
|
||||
Persist = (CRED_PERSIST)nativeCredential.Persist
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Invalid CriticalHandle!");
|
||||
}
|
||||
}
|
||||
|
||||
// Perform any specific actions to release the handle in the ReleaseHandle method.
|
||||
// Often, you need to use PInvoke to make a call into the Win32 API to release the
|
||||
// handle. In this case, however, we can use the Marshal class to release the unmanaged memory.
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
// If the handle was set, free it. Return success.
|
||||
if (!IsInvalid)
|
||||
{
|
||||
// NOTE: We should also ZERO out the memory allocated to the handle, before freeing it
|
||||
// so there are no traces of the sensitive data left in memory.
|
||||
CredFree(handle);
|
||||
|
||||
// Mark the handle as invalid for future users.
|
||||
SetHandleAsInvalid();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return false.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.NetFramework
|
||||
{
|
||||
|
||||
partial class PopupForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.webView1 = new Microsoft.Toolkit.Forms.UI.Controls.WebView();
|
||||
((System.ComponentModel.ISupportInitialize)(this.webView1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// webView1
|
||||
//
|
||||
this.webView1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.webView1.Location = new System.Drawing.Point(0, 0);
|
||||
this.webView1.MinimumSize = new System.Drawing.Size(20, 20);
|
||||
this.webView1.Name = "webView1";
|
||||
this.webView1.Size = new System.Drawing.Size(800, 450);
|
||||
this.webView1.TabIndex = 0;
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(800, 450);
|
||||
this.Controls.Add(this.webView1);
|
||||
this.Name = "Form1";
|
||||
this.Text = "Form1";
|
||||
((System.ComponentModel.ISupportInitialize)(this.webView1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Microsoft.Toolkit.Forms.UI.Controls.WebView webView1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.NetFramework
|
||||
{
|
||||
/// <summary>
|
||||
/// Service WebView for windows forms
|
||||
/// </summary>
|
||||
public partial class PopupForm : Form
|
||||
{
|
||||
private string initialHost;
|
||||
private string callbackHost;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current URL before closing the form
|
||||
/// </summary>
|
||||
public Uri ActualUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PopupForm"/> class.
|
||||
/// </summary>
|
||||
/// <param name="callbackUrl">Uri callback url</param>
|
||||
public PopupForm(Uri callbackUrl)
|
||||
{
|
||||
InitializeComponent();
|
||||
webView1.NavigationStarting += (s, e) => WebViewNavigationStartingHandler(e.Uri);
|
||||
callbackHost = GetTopLevelDomain(callbackUrl);
|
||||
}
|
||||
|
||||
private void WebViewNavigationStartingHandler(Uri uri)
|
||||
{
|
||||
var topLevelDomain = GetTopLevelDomain(uri);
|
||||
if (initialHost != topLevelDomain && topLevelDomain == callbackHost)
|
||||
{
|
||||
ActualUrl = uri;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a given url in the WebView
|
||||
/// </summary>
|
||||
/// <param name="url">Url string to navigate to.</param>
|
||||
public void NavigateTo(string url)
|
||||
{
|
||||
initialHost = GetTopLevelDomain(url);
|
||||
webView1.Navigate(url);
|
||||
}
|
||||
|
||||
private string GetTopLevelDomain(string url)
|
||||
{
|
||||
return GetTopLevelDomain(new Uri(url));
|
||||
}
|
||||
|
||||
private string GetTopLevelDomain(Uri url)
|
||||
{
|
||||
var hostParts = url.Host.Split('.').Select(x => x.ToString());
|
||||
if (hostParts.Count() > 1)
|
||||
{
|
||||
return hostParts.ElementAt(1);
|
||||
}
|
||||
|
||||
return hostParts.ElementAt(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
<Window x:Class="Microsoft.Toolkit.Services.PlatformSpecific.NetFramework.PopupWPF"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Microsoft.Toolkit.Services.PlatformSpecific.NetFramework"
|
||||
xmlns:Controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls.WebView"
|
||||
mc:Ignorable="d"
|
||||
Title="PopupPage" Height="450" Width="800">
|
||||
<Grid>
|
||||
<Controls:WebView Grid.Row="0" x:Name="WebView1" Width="800" Height="800" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
|
||||
</Grid>
|
||||
</Window>
|
|
@ -1,83 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.NetFramework
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for PopupWPF.xaml
|
||||
/// </summary>
|
||||
public partial class PopupWPF : Window
|
||||
{
|
||||
private string initialHost;
|
||||
private string callbackHost;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current URL before closing the form
|
||||
/// </summary>
|
||||
public Uri ActualUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PopupWPF"/> class.
|
||||
/// </summary>
|
||||
/// <param name="callbackUrl">Uri callback url</param>
|
||||
public PopupWPF(Uri callbackUrl)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
WebView1.NavigationStarting += (s, e) => WebViewNavigationStartingHandler(e.Uri);
|
||||
callbackHost = GetTopLevelDomain(callbackUrl);
|
||||
}
|
||||
|
||||
private void WebViewNavigationStartingHandler(Uri uri)
|
||||
{
|
||||
var topLevelDomain = GetTopLevelDomain(uri);
|
||||
if (initialHost != topLevelDomain && topLevelDomain == callbackHost)
|
||||
{
|
||||
ActualUrl = uri;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a given url in the WebView
|
||||
/// </summary>
|
||||
/// <param name="url">Url string to navigate to.</param>
|
||||
public void NavigateTo(string url)
|
||||
{
|
||||
initialHost = GetTopLevelDomain(url);
|
||||
WebView1.Navigate(url);
|
||||
}
|
||||
|
||||
private string GetTopLevelDomain(string url)
|
||||
{
|
||||
return GetTopLevelDomain(new Uri(url));
|
||||
}
|
||||
|
||||
private string GetTopLevelDomain(Uri url)
|
||||
{
|
||||
var hostParts = url.Host.Split('.').Select(x => x.ToString());
|
||||
if (hostParts.Count() > 1)
|
||||
{
|
||||
return hostParts.ElementAt(1);
|
||||
}
|
||||
|
||||
return hostParts.ElementAt(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
using Windows.Security.Authentication.Web;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.Uwp
|
||||
{
|
||||
/// <summary>
|
||||
/// Authentication Broker
|
||||
/// </summary>
|
||||
internal class UwpAuthenticationBroker : IAuthenticationBroker
|
||||
{
|
||||
/// <summary>
|
||||
/// Authentication process
|
||||
/// </summary>
|
||||
/// <param name="requestUri"> Request Uri</param>
|
||||
/// <param name="callbackUri"> Uri result</param>
|
||||
/// <returns> Returns login status</returns>
|
||||
public async Task<AuthenticationResult> Authenticate(Uri requestUri, Uri callbackUri)
|
||||
{
|
||||
WebAuthenticationResult result = await WebAuthenticationBroker.AuthenticateAsync(
|
||||
WebAuthenticationOptions.None,
|
||||
requestUri,
|
||||
callbackUri);
|
||||
|
||||
switch (result.ResponseStatus)
|
||||
{
|
||||
case WebAuthenticationStatus.Success:
|
||||
return new AuthenticationResult { ResponseData = result.ResponseData, ResponseStatus = AuthenticationResultStatus.Success };
|
||||
case WebAuthenticationStatus.UserCancel:
|
||||
return new AuthenticationResult { ResponseData = result.ResponseData, ResponseStatus = AuthenticationResultStatus.UserCancel, ResponseErrorDetail = result.ResponseErrorDetail };
|
||||
case WebAuthenticationStatus.ErrorHttp:
|
||||
return new AuthenticationResult { ResponseData = result.ResponseData, ResponseStatus = AuthenticationResultStatus.ErrorHttp, ResponseErrorDetail = result.ResponseErrorDetail };
|
||||
default:
|
||||
// TODO: Change with correct name;
|
||||
throw new ArgumentException("error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
using Windows.Security.Credentials;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.Uwp
|
||||
{
|
||||
/// <summary>
|
||||
/// Password Manager
|
||||
/// </summary>
|
||||
internal class UwpPasswordManager : IPasswordManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Password vault used to store access tokens
|
||||
/// </summary>
|
||||
private readonly PasswordVault _vault;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UwpPasswordManager"/> class.
|
||||
/// </summary>
|
||||
public UwpPasswordManager()
|
||||
{
|
||||
_vault = new PasswordVault();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Toolkit.Services.Core.PasswordCredential Get(string key)
|
||||
{
|
||||
var credentials = RetrievePasswordCredential(key);
|
||||
if (credentials == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Toolkit.Services.Core.PasswordCredential { Password = credentials.Password, UserName = credentials.UserName };
|
||||
}
|
||||
|
||||
private Windows.Security.Credentials.PasswordCredential RetrievePasswordCredential(string key)
|
||||
{
|
||||
var passwordCredentials = _vault.RetrieveAll();
|
||||
var temp = passwordCredentials.FirstOrDefault(c => c.Resource == key);
|
||||
|
||||
if (temp == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _vault.Retrieve(temp.Resource, temp.UserName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Remove(string key)
|
||||
{
|
||||
_vault.Remove(RetrievePasswordCredential(key));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Store(string resource, Toolkit.Services.Core.PasswordCredential credentials)
|
||||
{
|
||||
var passwordCredential = new Windows.Security.Credentials.PasswordCredential(resource, credentials.UserName, credentials.Password);
|
||||
_vault.Add(passwordCredential);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
|
||||
using Windows.Security.Cryptography;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.Uwp
|
||||
{
|
||||
/// <summary>
|
||||
/// UWP specific signature generator using cryptographic library
|
||||
/// </summary>
|
||||
internal class UwpSignatureManager : ISignatureManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Generate request signature.
|
||||
/// </summary>
|
||||
/// <param name="baseString">String to sign</param>
|
||||
/// <param name="secret">Secret to use to sign</param>
|
||||
/// <param name="append">If true append & to the base string</param>
|
||||
/// <returns>Signature.</returns>
|
||||
public string GetSignature(string baseString, string secret, bool append = false)
|
||||
{
|
||||
var key = append ? secret + "&" : secret;
|
||||
|
||||
IBuffer keyMaterial = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8);
|
||||
MacAlgorithmProvider mac = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha1);
|
||||
CryptographicKey cryptoKey = mac.CreateKey(keyMaterial);
|
||||
IBuffer dataToBeSigned = CryptographicBuffer.ConvertStringToBinary(baseString, BinaryStringEncoding.Utf8);
|
||||
IBuffer hash = CryptographicEngine.Sign(cryptoKey, dataToBeSigned);
|
||||
return CryptographicBuffer.EncodeToBase64String(hash);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
using Windows.Security.Credentials;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace Microsoft.Toolkit.Services.PlatformSpecific.Uwp
|
||||
{
|
||||
/// <summary>
|
||||
/// UWP specific implementation for IStorageManager using ApplicationData and LocalSettings
|
||||
/// </summary>
|
||||
internal class UwpStorageManager : IStorageManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Read the storage to return the key if exists if not null;
|
||||
/// </summary>
|
||||
/// <param name="key">Key to lookup</param>
|
||||
/// <returns>Return string value if exists if not null</returns>
|
||||
public Task<string> GetAsync(string key)
|
||||
{
|
||||
return Task.FromResult<string>(ApplicationData.Current.LocalSettings.Values[key]?.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the value in the key inside the storage
|
||||
/// </summary>
|
||||
/// <param name="key">Key name in storage</param>
|
||||
/// <param name="value">Value associated to the storage</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public Task SetAsync(string key, string value)
|
||||
{
|
||||
ApplicationData.Current.LocalSettings.Values[key] = value;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
||||
<Library Name="Microsoft.Toolkit.Services">
|
||||
<Namespace Name="System.Text.Json.Serialization.Converters" Dynamic="Required All"/>
|
||||
</Library>
|
||||
</Directives>
|
|
@ -1,22 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.LinkedIn
|
||||
{
|
||||
/// <summary>
|
||||
/// Constant strings for LinkedIn Service.
|
||||
/// </summary>
|
||||
public static class LinkedInConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// Storage key name for access token.
|
||||
/// </summary>
|
||||
public static readonly string STORAGEKEYACCESSTOKEN = "LinkedInAccessToken";
|
||||
|
||||
/// <summary>
|
||||
/// Storage key name for user name.
|
||||
/// </summary>
|
||||
public static readonly string STORAGEKEYUSER = "LinkedInUser";
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.LinkedIn
|
||||
{
|
||||
/// <summary>
|
||||
/// Strong type representation of Content.
|
||||
/// </summary>
|
||||
public class LinkedInContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets title property.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets description property.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets submitted url property.
|
||||
/// </summary>
|
||||
public string SubmittedUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets submitted image url property.
|
||||
/// </summary>
|
||||
public string SubmittedImageUrl { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.LinkedIn
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration object for specifying richer query information.
|
||||
/// </summary>
|
||||
public class LinkedInDataConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the query string for filtering service results.
|
||||
/// </summary>
|
||||
public string Query { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,334 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Toolkit.Services.Core;
|
||||
|
||||
#if WINRT
|
||||
using Microsoft.Toolkit.Services.PlatformSpecific.Uwp;
|
||||
#endif
|
||||
|
||||
#if NET462
|
||||
using Microsoft.Toolkit.Services.PlatformSpecific.NetFramework;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Toolkit.Services.LinkedIn
|
||||
{
|
||||
/// <summary>
|
||||
/// Data Provider for connecting to LinkedIn service.
|
||||
/// </summary>
|
||||
public class LinkedInDataProvider
|
||||
{
|
||||
private const string _oAuthBaseUrl = "https://www.linkedin.com/uas/oauth2/";
|
||||
private const string _baseUrl = "https://api.linkedin.com/v1";
|
||||
|
||||
private static HttpClient client = new HttpClient();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets logged in user information.
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the provider is already logged in
|
||||
/// </summary>
|
||||
public bool LoggedIn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets requiredPermissions property.
|
||||
/// </summary>
|
||||
public LinkedInPermissions RequiredPermissions { get; set; }
|
||||
|
||||
private readonly IAuthenticationBroker _authentication;
|
||||
private readonly IPasswordManager _passwordManager;
|
||||
private readonly IStorageManager _storageManager;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets tokens property.
|
||||
/// </summary>
|
||||
public LinkedInOAuthTokens Tokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LinkedInDataProvider"/> class.
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="tokens">OAuth tokens for request.</param>
|
||||
/// <param name="requiredPermissions">Required permissions for the session.</param>
|
||||
/// <param name="authentication">Authentication result interface.</param>
|
||||
/// <param name="passwordManager">Password Manager interface, store the password.</param>
|
||||
/// <param name="storageManager">Storage Manager interface.</param>
|
||||
public LinkedInDataProvider(LinkedInOAuthTokens tokens, LinkedInPermissions requiredPermissions, IAuthenticationBroker authentication, IPasswordManager passwordManager, IStorageManager storageManager)
|
||||
{
|
||||
if (string.IsNullOrEmpty(tokens.ClientSecret))
|
||||
{
|
||||
throw new ArgumentException("Missing client secret key");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tokens.ClientId))
|
||||
{
|
||||
throw new ArgumentException("Missing client ID");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tokens.CallbackUri))
|
||||
{
|
||||
throw new ArgumentException("Missing callback uri");
|
||||
}
|
||||
|
||||
// Check if its a valid combination of LinkedInPermissions
|
||||
if ((~(int)LinkedInPermissionsHelpers.AllPermissions & (int)requiredPermissions) != 0)
|
||||
{
|
||||
throw new ArgumentException("Error retrieving required permissions");
|
||||
}
|
||||
|
||||
Tokens = tokens;
|
||||
RequiredPermissions = requiredPermissions;
|
||||
_authentication = authentication ?? throw new ArgumentException("Invalid AuthenticationBroker");
|
||||
_storageManager = storageManager ?? throw new ArgumentException("Invalid StorageManager");
|
||||
_passwordManager = passwordManager ?? throw new ArgumentException("Invalid PasswordManager");
|
||||
}
|
||||
#if WINRT
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LinkedInDataProvider"/> class.
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="tokens">OAuth tokens for request.</param>
|
||||
/// <param name="requiredPermissions">Required permissions for the session.</param>
|
||||
public LinkedInDataProvider(LinkedInOAuthTokens tokens, LinkedInPermissions requiredPermissions)
|
||||
: this(tokens, requiredPermissions, new UwpAuthenticationBroker(), new UwpPasswordManager(), new UwpStorageManager())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NET462
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LinkedInDataProvider"/> class.
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="tokens">OAuth tokens for request.</param>
|
||||
/// <param name="requiredPermissions">Required permissions for the session.</param>
|
||||
public LinkedInDataProvider(LinkedInOAuthTokens tokens, LinkedInPermissions requiredPermissions)
|
||||
: this(tokens, requiredPermissions, new NetFrameworkAuthenticationBroker(), new NetFrameworkPasswordManager(), new NetFrameworkStorageManager())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Log user in to LinkedIn.
|
||||
/// </summary>
|
||||
/// <returns>Boolean indicating login success.</returns>
|
||||
public async Task<bool> LoginAsync()
|
||||
{
|
||||
var user = await _storageManager.GetAsync(LinkedInConstants.STORAGEKEYUSER);
|
||||
var credential = _passwordManager.Get(LinkedInConstants.STORAGEKEYACCESSTOKEN);
|
||||
if (!string.IsNullOrEmpty(user) && credential != null)
|
||||
{
|
||||
Tokens.AccessToken = credential.Password;
|
||||
Username = user;
|
||||
LoggedIn = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
string authorizeCode = await GetAuthorizeCodeAsync(Tokens, RequiredPermissions);
|
||||
|
||||
if (!string.IsNullOrEmpty(authorizeCode))
|
||||
{
|
||||
var accessToken = await GetAccessTokenAsync(Tokens, authorizeCode);
|
||||
|
||||
if (!string.IsNullOrEmpty(accessToken))
|
||||
{
|
||||
Tokens.AccessToken = accessToken;
|
||||
|
||||
_passwordManager.Store(LinkedInConstants.STORAGEKEYACCESSTOKEN, new PasswordCredential { UserName = LinkedInConstants.STORAGEKEYUSER, Password = accessToken });
|
||||
await _storageManager.SetAsync(LinkedInConstants.STORAGEKEYUSER, LinkedInConstants.STORAGEKEYUSER);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LoggedIn = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log user out of LinkedIn.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public async Task LogoutAsync()
|
||||
{
|
||||
var credential = _passwordManager.Get(LinkedInConstants.STORAGEKEYACCESSTOKEN);
|
||||
|
||||
if (credential != null)
|
||||
{
|
||||
_passwordManager.Remove(LinkedInConstants.STORAGEKEYACCESSTOKEN);
|
||||
await _storageManager.SetAsync(LinkedInConstants.STORAGEKEYUSER, null);
|
||||
}
|
||||
|
||||
LoggedIn = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around REST API for making data request.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSchema">Schema to use</typeparam>
|
||||
/// <param name="config">Query configuration.</param>
|
||||
/// <param name="maxRecords">Upper limit for records returned.</param>
|
||||
/// <param name="startRecord">Index of paged results.</param>
|
||||
/// <param name="fields">A comma separated string of required fields, which will have strongly typed representation in the model passed in.</param>
|
||||
/// <returns>Strongly typed list of results.</returns>
|
||||
public async Task<IEnumerable<TSchema>> GetDataAsync<TSchema>(LinkedInDataConfig config, int maxRecords, int startRecord = 0, string fields = "id")
|
||||
{
|
||||
var parser = new LinkedInParser<TSchema>();
|
||||
|
||||
var url = $"{_baseUrl}{config.Query}/~:({fields})?oauth2_access_token={Tokens.AccessToken}&format=json&count={maxRecords}&start={startRecord}";
|
||||
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(url));
|
||||
request.Headers.Connection.TryParseAdd("Keep-Alive");
|
||||
|
||||
using var response = await client.SendAsync(request).ConfigureAwait(false);
|
||||
var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
|
||||
if (response.IsSuccessStatusCode && !string.IsNullOrEmpty(data))
|
||||
{
|
||||
return parser.Parse(data);
|
||||
}
|
||||
|
||||
throw new RequestFailedException((System.Net.HttpStatusCode)response.StatusCode, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Share data to LinkedIn.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Schema of data to share.</typeparam>
|
||||
/// <typeparam name="U">Type of response object.</typeparam>
|
||||
/// <param name="dataToShare">Share request content.</param>
|
||||
/// <returns>Boolean indicating success or failure.</returns>
|
||||
public async Task<U> ShareDataAsync<T, U>(T dataToShare)
|
||||
{
|
||||
var shareRequest = dataToShare as LinkedInShareRequest;
|
||||
if (shareRequest != null)
|
||||
{
|
||||
LinkedInVisibility.ParseVisibilityStringToEnum(shareRequest.Visibility.Code);
|
||||
|
||||
var requestParser = new LinkedInParser<LinkedInShareRequest>();
|
||||
|
||||
var url = $"{_baseUrl}/people/~/shares?oauth2_access_token={Tokens.AccessToken}&format=json";
|
||||
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(url));
|
||||
request.Headers.Add("x-li-format", "json");
|
||||
var stringContent = requestParser.Parse(shareRequest);
|
||||
request.Content = new StringContent(stringContent, Encoding.UTF8, "application/json");
|
||||
|
||||
using var response = await client.SendAsync(request).ConfigureAwait(false);
|
||||
var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
|
||||
var responseParser = new LinkedInParser<U>();
|
||||
|
||||
var listResults = responseParser.Parse(data) as List<U>;
|
||||
return listResults[0];
|
||||
}
|
||||
|
||||
return default(U);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check validity of configuration.
|
||||
/// </summary>
|
||||
/// <param name="config">Query configuration.</param>
|
||||
protected void ValidateConfig(LinkedInDataConfig config)
|
||||
{
|
||||
if (config?.Query == null)
|
||||
{
|
||||
throw new ConfigParameterNullException(nameof(config.Query));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> GetAccessTokenAsync(LinkedInOAuthTokens tokens, string authorizeCode)
|
||||
{
|
||||
var url = $"{_oAuthBaseUrl}accessToken?grant_type=authorization_code"
|
||||
+ "&code=" + authorizeCode
|
||||
+ "&redirect_uri=" + Uri.EscapeDataString(tokens.CallbackUri)
|
||||
+ "&client_id=" + tokens.ClientId
|
||||
+ "&client_secret=" + tokens.ClientSecret;
|
||||
|
||||
using var request = new HttpRequestMessage(HttpMethod.Post, new Uri(url));
|
||||
using var response = await client.SendAsync(request).ConfigureAwait(false);
|
||||
using var jsonStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
using var jsonDoc = await JsonDocument.ParseAsync(jsonStream).ConfigureAwait(false);
|
||||
|
||||
var value = jsonDoc.RootElement.GetProperty("access_token");
|
||||
return value.GetString();
|
||||
}
|
||||
|
||||
private async Task<string> GetAuthorizeCodeAsync(LinkedInOAuthTokens tokens, LinkedInPermissions permissions)
|
||||
{
|
||||
string scopes = ConvertPermissionsToEncodedScopeString(permissions);
|
||||
|
||||
var url = $"{_oAuthBaseUrl}authorization?response_type=code"
|
||||
+ "&client_id=" + tokens.ClientId
|
||||
+ "&state=STATE"
|
||||
+ "&redirect_uri=" + Uri.EscapeDataString(tokens.CallbackUri)
|
||||
+ "&" + scopes;
|
||||
|
||||
var startUri = new Uri(url);
|
||||
var endUri = new Uri(tokens.CallbackUri);
|
||||
|
||||
var result = await _authentication.Authenticate(startUri, endUri);
|
||||
switch (result.ResponseStatus)
|
||||
{
|
||||
case AuthenticationResultStatus.Success:
|
||||
{
|
||||
var response = result.ResponseData;
|
||||
IDictionary<string, string> dictionary = new Dictionary<string, string>();
|
||||
var split = response.Split('?');
|
||||
foreach (var keyValue in split[split.Length - 1].Split('&'))
|
||||
{
|
||||
var keyValueSplit = keyValue.Split('=');
|
||||
if (keyValueSplit.Length == 2)
|
||||
{
|
||||
dictionary.Add(keyValueSplit[0], keyValueSplit[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return dictionary["code"];
|
||||
}
|
||||
|
||||
case AuthenticationResultStatus.ErrorHttp:
|
||||
Debug.WriteLine("WAB failed, message={0}", result.ResponseErrorDetail.ToString());
|
||||
return string.Empty;
|
||||
|
||||
case AuthenticationResultStatus.UserCancel:
|
||||
Debug.WriteLine("WAB user aborted.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private string ConvertPermissionsToEncodedScopeString(LinkedInPermissions requiredPermissions)
|
||||
{
|
||||
StringBuilder scope = new StringBuilder();
|
||||
|
||||
foreach (LinkedInPermissions value in Enum.GetValues(typeof(LinkedInPermissions)))
|
||||
{
|
||||
if ((requiredPermissions & value) != LinkedInPermissions.NotSet)
|
||||
{
|
||||
var name = value.ToString().ToLower();
|
||||
name = name.Replace("readwrite", "rw_");
|
||||
name = name.Replace("read", "r_");
|
||||
name = name.Replace("write", "w_");
|
||||
name = name.Replace("companyadmin", "company_admin");
|
||||
|
||||
scope.Append($"{name} ");
|
||||
}
|
||||
}
|
||||
|
||||
return "scope=" + Uri.EscapeDataString(scope.ToString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Services.LinkedIn
|
||||
{
|
||||
/// <summary>
|
||||
/// LinkedIn OAuth tokens.
|
||||
/// </summary>
|
||||
public class LinkedInOAuthTokens
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets clientId.
|
||||
/// </summary>
|
||||
public string ClientId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets clientSecret.
|
||||
/// </summary>
|
||||
public string ClientSecret { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets callback Uri.
|
||||
/// </summary>
|
||||
public string CallbackUri { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets access token.
|
||||
/// </summary>
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets access token Secret.
|
||||
/// </summary>
|
||||
public string AccessTokenSecret { get; set; }
|
||||
}
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче