Skip to content

Commit 7268203

Browse files
committed
Add clone methods
1 parent 12cdb1b commit 7268203

File tree

12 files changed

+178
-29
lines changed

12 files changed

+178
-29
lines changed

AdvancedSharpAdbClient/AdbClient.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace AdvancedSharpAdbClient
2828
/// <para><seealso href="https://github.com/android/platform_system_core/blob/master/adb/adb_client.c">adb_client.c</seealso></para>
2929
/// <para><seealso href="https://github.com/android/platform_system_core/blob/master/adb/adb.c">adb.c</seealso></para>
3030
/// </remarks>
31-
public partial class AdbClient : IAdbClient
31+
public partial class AdbClient : IAdbClient, ICloneable<IAdbClient>, ICloneable
3232
#if WINDOWS_UWP || WINDOWS10_0_17763_0_OR_GREATER
3333
, IAdbClient.IWinRT
3434
#endif
@@ -143,7 +143,7 @@ public AdbClient(Func<EndPoint, IAdbSocket> adbSocketFactory)
143143
/// <summary>
144144
/// Gets the <see cref="System.Net.EndPoint"/> at which the adb server is listening.
145145
/// </summary>
146-
public EndPoint EndPoint { get; protected set; }
146+
public EndPoint EndPoint { get; init; }
147147

148148
/// <summary>
149149
/// Create an ASCII string preceded by four hex digits. The opening "####"
@@ -1118,6 +1118,19 @@ public IEnumerable<string> GetFeatureSet(DeviceData device)
11181118
return featureList;
11191119
}
11201120

1121+
/// <summary>
1122+
/// Creates a new <see cref="AdbClient"/> object that is a copy of the current instance with new <see cref="EndPoint"/>.
1123+
/// </summary>
1124+
/// <param name="endPoint">The new <see cref="EndPoint"/> to use.</param>
1125+
/// <returns>A new <see cref="AdbClient"/> object that is a copy of this instance with new <see cref="EndPoint"/>.</returns>
1126+
public AdbClient Clone(EndPoint endPoint) => new(endPoint, AdbSocketFactory);
1127+
1128+
/// <inheritdoc/>
1129+
public IAdbClient Clone() => new AdbClient(EndPoint, AdbSocketFactory);
1130+
1131+
/// <inheritdoc/>
1132+
object ICloneable.Clone() => Clone();
1133+
11211134
/// <summary>
11221135
/// Sets default encoding (default - UTF8).
11231136
/// </summary>

AdvancedSharpAdbClient/AdbCommandLineClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public AdbCommandLineClient(string adbPath, bool isForce = false, ILogger<AdbCom
5757
/// <summary>
5858
/// Gets the path to the <c>adb.exe</c> executable.
5959
/// </summary>
60-
public string AdbPath { get; protected set; }
60+
public string AdbPath { get; init; }
6161

6262
/// <inheritdoc/>
6363
public AdbCommandLineStatus GetVersion()

AdvancedSharpAdbClient/AdbServer.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace AdvancedSharpAdbClient
1818
/// giant multiplexing loop whose purpose is to orchestrate the exchange of data
1919
/// between clients and devices.</para>
2020
/// </summary>
21-
public partial class AdbServer : IAdbServer
21+
public partial class AdbServer : IAdbServer, ICloneable<IAdbServer>, ICloneable
2222
{
2323
/// <summary>
2424
/// The minimum version of <c>adb.exe</c> that is supported by this library.
@@ -162,7 +162,7 @@ public AdbServer(Func<EndPoint, IAdbSocket> adbSocketFactory, Func<string, IAdbC
162162
/// <summary>
163163
/// Gets the <see cref="System.Net.EndPoint"/> at which the adb server is listening.
164164
/// </summary>
165-
public EndPoint EndPoint { get; protected set; }
165+
public EndPoint EndPoint { get; init; }
166166

167167
/// <inheritdoc/>
168168
public StartServerResult StartServer(string adbPath, bool restartServerIfNewer = false)
@@ -261,5 +261,18 @@ public AdbServerStatus GetStatus()
261261
}
262262
}
263263
}
264+
265+
/// <summary>
266+
/// Creates a new <see cref="AdbServer"/> object that is a copy of the current instance with new <see cref="EndPoint"/>.
267+
/// </summary>
268+
/// <param name="endPoint">The new <see cref="EndPoint"/> to use.</param>
269+
/// <returns>A new <see cref="AdbServer"/> object that is a copy of this instance with new <see cref="EndPoint"/>.</returns>
270+
public AdbServer Clone(EndPoint endPoint) => new(endPoint, AdbSocketFactory, AdbCommandLineClientFactory);
271+
272+
/// <inheritdoc/>
273+
public IAdbServer Clone() => new AdbServer(EndPoint, AdbSocketFactory, AdbCommandLineClientFactory);
274+
275+
/// <inheritdoc/>
276+
object ICloneable.Clone() => Clone();
264277
}
265278
}

AdvancedSharpAdbClient/AdbSocket.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace AdvancedSharpAdbClient
2323
/// </summary>
2424
/// <param name="socket">The <see cref="ITcpSocket"/> at which the Android Debug Bridge is listening for clients.</param>
2525
/// <param name="logger">The logger to use when logging.</param>
26-
public partial class AdbSocket(ITcpSocket socket, ILogger<AdbSocket>? logger = null) : IAdbSocket
26+
public partial class AdbSocket(ITcpSocket socket, ILogger<AdbSocket>? logger = null) : IAdbSocket, ICloneable<IAdbSocket>, ICloneable
2727
{
2828
/// <summary>
2929
/// The logger to use when logging messages.
@@ -538,6 +538,20 @@ public void Dispose()
538538
/// <inheritdoc/>
539539
public void Close() => Socket.Dispose();
540540

541+
/// <inheritdoc/>
542+
public IAdbSocket Clone()
543+
{
544+
if (Socket is not ICloneable<ITcpSocket> cloneable)
545+
{
546+
throw new NotSupportedException($"{Socket.GetType()} does not support cloning.");
547+
}
548+
ITcpSocket socket = cloneable.Clone();
549+
return new AdbSocket(socket, logger);
550+
}
551+
552+
/// <inheritdoc/>
553+
object ICloneable.Clone() => Clone();
554+
541555
/// <summary>
542556
/// Creates a new <see cref="TcpSocket"/> instance based on the specified <see cref="EndPoint"/>.
543557
/// </summary>

AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -401,34 +401,34 @@ public void Deconstruct(out IAdbClient client, out DeviceData device)
401401
device = Device;
402402
}
403403

404+
#if !NET40_OR_GREATER && !NETCOREAPP2_0_OR_GREATER && !NETSTANDARD2_0_OR_GREATER && !UAP10_0_15138_0
405+
/// <inheritdoc/>
406+
public override int GetHashCode() => HashCode.Combine(EqualityContract, AdbClient, Device);
407+
408+
/// <inheritdoc/>
409+
public virtual bool Equals(DeviceClient? other) =>
410+
(object?)this == other ||
411+
(other != (object?)null
412+
&& EqualityComparer<Type>.Default.Equals(EqualityContract, other.EqualityContract)
413+
&& EqualityComparer<IAdbClient>.Default.Equals(AdbClient, other.AdbClient)
414+
&& EqualityComparer<DeviceData>.Default.Equals(Device, other.Device));
415+
#endif
416+
404417
/// <summary>
405418
/// Throws an <see cref="ArgumentNullException"/> if the <paramref name="device"/>
406419
/// parameter is <see langword="null"/>, and a <see cref="ArgumentOutOfRangeException"/>
407420
/// if <paramref name="device"/> does not have a valid serial number.
408421
/// </summary>
409422
/// <param name="device">A <see cref="DeviceData"/> object to validate.</param>
410423
/// <returns>The <paramref name="device"/> parameter, if it is valid.</returns>
411-
protected static DeviceData EnsureDevice([NotNull] DeviceData? device)
424+
private static DeviceData EnsureDevice([NotNull] DeviceData? device)
412425
{
413426
ExceptionExtensions.ThrowIfNull(device);
414427
return device.IsEmpty
415428
? throw new ArgumentOutOfRangeException(nameof(device), "You must specific a serial number for the device")
416429
: device;
417430
}
418431

419-
#if !NET40_OR_GREATER && !NETCOREAPP2_0_OR_GREATER && !NETSTANDARD2_0_OR_GREATER && !UAP10_0_15138_0
420-
/// <inheritdoc/>
421-
public override int GetHashCode() => HashCode.Combine(EqualityContract, AdbClient, Device);
422-
423-
/// <inheritdoc/>
424-
public virtual bool Equals(DeviceClient? other) =>
425-
(object?)this == other ||
426-
(other != (object?)null
427-
&& EqualityComparer<Type>.Default.Equals(EqualityContract, other.EqualityContract)
428-
&& EqualityComparer<IAdbClient>.Default.Equals(AdbClient, other.AdbClient)
429-
&& EqualityComparer<DeviceData>.Default.Equals(Device, other.Device));
430-
#endif
431-
432432
#if NET7_0_OR_GREATER
433433
[GeneratedRegex("<\\?xml(.?)*")]
434434
private static partial Regex GetXmlRegex();

AdvancedSharpAdbClient/DeviceMonitor.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace AdvancedSharpAdbClient
3333
/// }
3434
/// </code>
3535
/// </example>
36-
public partial class DeviceMonitor : IDeviceMonitor
36+
public partial class DeviceMonitor : IDeviceMonitor, ICloneable<IDeviceMonitor>, ICloneable
3737
#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
3838
, IAsyncDisposable
3939
#endif
@@ -399,5 +399,18 @@ protected virtual void UpdateDevices(IEnumerable<DeviceData> collection)
399399
}
400400
}
401401
}
402+
403+
/// <inheritdoc/>
404+
public IDeviceMonitor Clone()
405+
{
406+
if (Socket is not ICloneable<IAdbSocket> cloneable)
407+
{
408+
throw new NotSupportedException($"{Socket.GetType()} does not support cloning.");
409+
}
410+
return new DeviceMonitor(cloneable.Clone(), logger);
411+
}
412+
413+
/// <inheritdoc/>
414+
object ICloneable.Clone() => Clone();
402415
}
403416
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// <copyright file="ICloneable.cs" company="The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere">
2+
// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved.
3+
// </copyright>
4+
5+
using System;
6+
7+
#if !NETFRAMEWORK && !NETCOREAPP2_0_OR_GREATER && !NETSTANDARD2_0_OR_GREATER && !UAP10_0_15138_0
8+
// Licensed to the .NET Foundation under one or more agreements.
9+
// The .NET Foundation licenses this file to you under the MIT license.
10+
11+
namespace System
12+
{
13+
/// <summary>
14+
/// Supports cloning, which creates a new instance of a class with the same value as an existing instance.
15+
/// </summary>
16+
internal interface ICloneable
17+
{
18+
/// <summary>
19+
/// Creates a new object that is a copy of the current instance.
20+
/// </summary>
21+
/// <returns>A new object that is a copy of this instance.</returns>
22+
object Clone();
23+
}
24+
}
25+
26+
namespace AdvancedSharpAdbClient.Polyfills
27+
{
28+
/// <summary>
29+
/// Supports cloning, which creates a new instance of a class with the same value as an existing instance.
30+
/// </summary>
31+
/// <typeparam name="T">The type of the class.</typeparam>
32+
public interface ICloneable<T>
33+
{
34+
/// <summary>
35+
/// Creates a new <typeparamref name="T"/> object that is a copy of the current instance.
36+
/// </summary>
37+
/// <returns>A new <typeparamref name="T"/> object that is a copy of this instance.</returns>
38+
T Clone();
39+
}
40+
}
41+
#else
42+
namespace AdvancedSharpAdbClient.Polyfills
43+
{
44+
/// <summary>
45+
/// Supports cloning, which creates a new instance of a class with the same value as an existing instance.
46+
/// </summary>
47+
/// <typeparam name="T">The type of the class.</typeparam>
48+
public interface ICloneable<T> : ICloneable
49+
{
50+
/// <summary>
51+
/// Creates a new <typeparamref name="T"/> object that is a copy of the current instance.
52+
/// </summary>
53+
/// <returns>A new <typeparamref name="T"/> object that is a copy of this instance.</returns>
54+
new T Clone();
55+
}
56+
}
57+
#endif

AdvancedSharpAdbClient/Polyfills/Interfaces/IDisposableWithTask.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#if HAS_TASK
2-
// Licensed to the .NET Foundation under one or more agreements.
3-
// The .NET Foundation licenses this file to you under the MIT license.
2+
// <copyright file="IDisposableWithTask.cs" company="The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere">
3+
// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved.
4+
// </copyright>
45

56
using System.ComponentModel;
67

AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyCollection.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
// Licensed to the .NET Foundation under one or more agreements.
33
// The .NET Foundation licenses this file to you under the MIT license.
44

5-
using System.Collections.Generic;
65
using System.ComponentModel;
76

8-
namespace AdvancedSharpAdbClient.Polyfills
7+
namespace System.Collections.Generic
98
{
109
/// <summary>
1110
/// Represents a strongly-typed, read-only collection of elements.

AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyList.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
using System.ComponentModel;
66

7-
namespace AdvancedSharpAdbClient.Polyfills
7+
namespace System.Collections.Generic
88
{
99
/// <summary>
1010
/// Represents a read-only collection of elements that can be accessed by index.

0 commit comments

Comments
 (0)