< Summary

Information
Class: Ice.ObjectPrxHelperBase.GetConnectionTaskCompletionCallback
Assembly: Ice
File(s): /_/csharp/src/Ice/Proxy.cs
Tag: 125_37167941578
Line coverage
100%
Covered lines: 3
Uncovered lines: 0
Coverable lines: 3
Total lines: 1942
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage
100%
Covered methods: 2
Fully covered methods: 2
Total methods: 2
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
handleInvokeResponse(...)100%11100%

File(s)

/_/csharp/src/Ice/Proxy.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using Ice.Internal;
 6using System.ComponentModel;
 7using System.Diagnostics.CodeAnalysis;
 8
 9namespace Ice;
 10
 11/// <summary>
 12/// The base interface of all Ice proxies.
 13/// </summary>
 14public interface ObjectPrx : IEquatable<ObjectPrx>
 15{
 16    /// <summary>
 17    /// Gets the communicator that created this proxy.
 18    /// </summary>
 19    /// <returns>The communicator that created this proxy.</returns>
 20    Communicator ice_getCommunicator();
 21
 22    /// <summary>
 23    /// Tests whether this object supports a specific Slice interface.
 24    /// </summary>
 25    /// <param name="id">The type ID of the Slice interface to test against.</param>
 26    /// <param name="context">The request context.</param>
 27    /// <returns><see langword="true"/> if the target object implements the Slice interface specified by
 28    /// <paramref name="id"/> or implements a derived interface; otherwise, <see langword="false"/>.</returns>
 29    bool ice_isA(string id, Dictionary<string, string>? context = null);
 30
 31    /// <summary>
 32    /// Tests whether this object supports a specific Slice interface.
 33    /// </summary>
 34    /// <param name="id">The type ID of the Slice interface to test against.</param>
 35    /// <param name="context">The request context.</param>
 36    /// <param name="progress">Sent progress provider.</param>
 37    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 38    /// <returns>A task that will complete with <see langword="true"/> if the target object implements the Slice
 39    /// interface specified by <paramref name="id"/> or implements a derived interface; otherwise,
 40    /// <see langword="false"/>.</returns>
 41    Task<bool> ice_isAAsync(
 42        string id,
 43        Dictionary<string, string>? context = null,
 44        IProgress<bool>? progress = null,
 45        CancellationToken cancel = default);
 46
 47    /// <summary>
 48    /// Tests whether the target object of this proxy can be reached.
 49    /// </summary>
 50    /// <param name="context">The request context.</param>
 51    void ice_ping(Dictionary<string, string>? context = null);
 52
 53    /// <summary>
 54    /// Tests whether the target object of this proxy can be reached.
 55    /// </summary>
 56    /// <param name="context">The request context.</param>
 57    /// <param name="progress">Sent progress provider.</param>
 58    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 59    /// <returns>A task that completes when the invocation completes.</returns>
 60    Task ice_pingAsync(
 61        Dictionary<string, string>? context = null,
 62        IProgress<bool>? progress = null,
 63        CancellationToken cancel = default);
 64
 65    /// <summary>
 66    /// Returns the Slice interfaces supported by this object as a list of Slice type IDs.
 67    /// </summary>
 68    /// <param name="context">The request context.</param>
 69    /// <returns>The Slice type IDs of the interfaces supported by this object, in alphabetical order.</returns>
 70    string[] ice_ids(Dictionary<string, string>? context = null);
 71
 72    /// <summary>
 73    /// Returns the Slice interfaces supported by this object as a list of Slice type IDs.
 74    /// </summary>
 75    /// <param name="context">The request context.</param>
 76    /// <param name="progress">Sent progress provider.</param>
 77    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 78    /// <returns>A task that will complete with The Slice type IDs of the interfaces supported by this object,
 79    /// in alphabetical order.</returns>
 80    Task<string[]> ice_idsAsync(
 81        Dictionary<string, string>? context = null,
 82        IProgress<bool>? progress = null,
 83        CancellationToken cancel = default);
 84
 85    /// <summary>
 86    /// Gets the Slice type ID of the most-derived interface supported by the target object of this proxy.
 87    /// </summary>
 88    /// <param name="context">The request context.</param>
 89    /// <returns>The Slice type ID of the most-derived interface.</returns>
 90    string ice_id(Dictionary<string, string>? context = null);
 91
 92    /// <summary>
 93    /// Gets the Slice type ID of the most-derived interface supported by the target object of this proxy.
 94    /// </summary>
 95    /// <param name="context">The request context.</param>
 96    /// <param name="progress">Sent progress provider.</param>
 97    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 98    /// <returns>The task object representing the asynchronous operation.</returns>
 99    Task<string> ice_idAsync(
 100        Dictionary<string, string>? context = null,
 101        IProgress<bool>? progress = null,
 102        CancellationToken cancel = default);
 103
 104    /// <summary>
 105    /// Invokes an operation dynamically.
 106    /// </summary>
 107    /// <param name="operation">The name of the operation to invoke.</param>
 108    /// <param name="mode">The operation mode (normal or idempotent).</param>
 109    /// <param name="inEncaps">The encoded in-parameters for the operation. You can pass an empty byte array when the
 110    /// operation takes no in-parameters; the Ice runtime then marshals an empty encapsulation.</param>
 111    /// <param name="outEncaps">The encoded out-parameters and return value
 112    /// for the operation. The return value follows any out-parameters.</param>
 113    /// <param name="context">The request context.</param>
 114    /// <returns>If the operation completed successfully, the return value is <see langword="true"/>.
 115    /// If the operation raises a user exception, the return value is <see langword="false"/>; in this case,
 116    /// <paramref name="outEncaps"/> contains the encoded user exception. If the operation raises a runtime exception,
 117    /// it throws it directly. When this proxy is a oneway, datagram, or batch proxy, the return value is always
 118    /// <see langword="true"/> and <paramref name="outEncaps"/> is empty.</returns>
 119    bool ice_invoke(
 120        string operation,
 121        OperationMode mode,
 122        byte[] inEncaps,
 123        out byte[] outEncaps,
 124        Dictionary<string, string>? context = null);
 125
 126    /// <summary>
 127    /// Invokes an operation dynamically.
 128    /// </summary>
 129    /// <param name="operation">The name of the operation to invoke.</param>
 130    /// <param name="mode">The operation mode (normal or idempotent).</param>
 131    /// <param name="inEncaps">The encoded in-parameters for the operation. You can pass an empty byte array when the
 132    /// operation takes no in-parameters; the Ice runtime then marshals an empty encapsulation.</param>
 133    /// <param name="context">The request context.</param>
 134    /// <param name="progress">Sent progress provider.</param>
 135    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 136    /// <returns>The task object representing the asynchronous operation. When this proxy is a oneway, datagram, or
 137    /// batch proxy, the task completes with <c>returnValue</c> set to <see langword="true"/> and an empty
 138    /// <c>outEncaps</c>.</returns>
 139    Task<Object_Ice_invokeResult>
 140    ice_invokeAsync(
 141        string operation,
 142        OperationMode mode,
 143        byte[] inEncaps,
 144        Dictionary<string, string>? context = null,
 145        IProgress<bool>? progress = null,
 146        CancellationToken cancel = default);
 147
 148    /// <summary>
 149    /// Gets the identity embedded in this proxy.
 150    /// </summary>
 151    /// <returns>The identity of the target object.</returns>
 152    Identity ice_getIdentity();
 153
 154    /// <summary>
 155    /// Creates a new proxy that is identical to this proxy, except for the proxy identity.
 156    /// </summary>
 157    /// <param name="newIdentity">The identity for the new proxy.</param>
 158    /// <returns>The new proxy with the specified identity.</returns>
 159    ObjectPrx ice_identity(Identity newIdentity);
 160
 161    /// <summary>
 162    /// Gets the per-proxy context for this proxy.
 163    /// </summary>
 164    /// <returns>A copy of the per-proxy context. The dictionary is empty when this proxy has no per-proxy
 165    /// context.</returns>
 166    Dictionary<string, string> ice_getContext();
 167
 168    /// <summary>
 169    /// Creates a new proxy that is identical to this proxy, except for the per-proxy context.
 170    /// </summary>
 171    /// <param name="newContext">The context for the new proxy.</param>
 172    /// <returns>The proxy with the new per-proxy context.</returns>
 173    ObjectPrx ice_context(Dictionary<string, string> newContext);
 174
 175    /// <summary>
 176    /// Gets the facet for this proxy.
 177    /// </summary>
 178    /// <returns>The facet for this proxy. If the proxy uses the default facet, the return value is the
 179    /// empty string.</returns>
 180    string ice_getFacet();
 181
 182    /// <summary>
 183    /// Creates a new proxy that is identical to this proxy, except for the facet.
 184    /// </summary>
 185    /// <param name="newFacet">The facet for the new proxy.</param>
 186    /// <returns>The proxy with the new facet.</returns>
 187    ObjectPrx ice_facet(string newFacet);
 188
 189    /// <summary>
 190    /// Gets the adapter ID for this proxy.
 191    /// </summary>
 192    /// <returns>The adapter ID. If the proxy does not have an adapter ID, the return value is the
 193    /// empty string.</returns>
 194    string ice_getAdapterId();
 195
 196    /// <summary>
 197    /// Creates a new proxy that is identical to this proxy, except for the adapter ID.
 198    /// </summary>
 199    /// <param name="newAdapterId">The adapter ID for the new proxy.</param>
 200    /// <returns>The proxy with the new adapter ID.</returns>
 201    ObjectPrx ice_adapterId(string newAdapterId);
 202
 203    /// <summary>
 204    /// Gets the endpoints used by this proxy.
 205    /// </summary>
 206    /// <returns>The endpoints used by this proxy.</returns>
 207    Endpoint[] ice_getEndpoints();
 208
 209    /// <summary>
 210    /// Creates a new proxy that is identical to this proxy, except for the endpoints.
 211    /// </summary>
 212    /// <param name="newEndpoints">The endpoints for the new proxy.</param>
 213    /// <returns>The proxy with the new endpoints.</returns>
 214    ObjectPrx ice_endpoints(Endpoint[] newEndpoints);
 215
 216    /// <summary>
 217    /// Gets the locator cache timeout of this proxy.
 218    /// </summary>
 219    /// <returns>The locator cache timeout value.</returns>
 220    TimeSpan ice_getLocatorCacheTimeout();
 221
 222    /// <summary>
 223    /// Creates a new proxy that is identical to this proxy, except for the locator cache timeout.
 224    /// </summary>
 225    /// <param name="newTimeout">The new locator cache timeout (in seconds). Any negative value means infinite
 226    /// and is normalized to -1.</param>
 227    ObjectPrx ice_locatorCacheTimeout(int newTimeout);
 228
 229    /// <summary>
 230    /// Creates a new proxy that is identical to this proxy, except for the locator cache timeout.
 231    /// </summary>
 232    /// <param name="newTimeout">The new locator cache timeout. Any negative timeout means infinite and is
 233    /// normalized to -1 second; a timeout that is not a whole number of seconds is rounded up to the next whole
 234    /// number of seconds.</param>
 235    /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="newTimeout"/> is greater than
 236    /// <see cref="int.MaxValue"/> seconds.</exception>
 237    ObjectPrx ice_locatorCacheTimeout(TimeSpan newTimeout);
 238
 239    /// <summary>
 240    /// Creates a new proxy that is identical to this proxy, except for the invocation timeout.
 241    /// </summary>
 242    /// <param name="newTimeout">The new invocation timeout (in milliseconds). Zero or any negative value means
 243    /// infinite and is normalized to -1.</param>
 244    ObjectPrx ice_invocationTimeout(int newTimeout);
 245
 246    /// <summary>
 247    /// Creates a new proxy that is identical to this proxy, except for the invocation timeout.
 248    /// </summary>
 249    /// <param name="newTimeout">The new invocation timeout. Zero or any negative timeout means infinite and is
 250    /// normalized to -1 millisecond; a timeout that is not a whole number of milliseconds is rounded up to the next
 251    /// whole number of milliseconds.</param>
 252    /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="newTimeout"/> is greater than
 253    /// <see cref="int.MaxValue"/> milliseconds.</exception>
 254    ObjectPrx ice_invocationTimeout(TimeSpan newTimeout);
 255
 256    /// <summary>
 257    /// Gets the invocation timeout of this proxy.
 258    /// </summary>
 259    /// <returns>The invocation timeout value.</returns>
 260    TimeSpan ice_getInvocationTimeout();
 261
 262    /// <summary>
 263    /// Returns whether this proxy caches connections.
 264    /// </summary>
 265    /// <returns><see langword="true"/> if this proxy caches connections; otherwise, <see langword="false"/>.</returns>
 266    bool ice_isConnectionCached();
 267
 268    /// <summary>
 269    /// Creates a new proxy that is identical to this proxy, except for connection caching.
 270    /// </summary>
 271    /// <param name="newCache"><see langword="true"/> if the new proxy should cache connections; otherwise,
 272    /// <see langword="false"/>.</param>
 273    /// <returns>The new proxy with the specified caching policy.</returns>
 274    ObjectPrx ice_connectionCached(bool newCache);
 275
 276    /// <summary>
 277    /// Returns how this proxy selects endpoints (randomly or ordered).
 278    /// </summary>
 279    /// <returns>The endpoint selection policy.</returns>
 280    EndpointSelectionType ice_getEndpointSelection();
 281
 282    /// <summary>
 283    /// Creates a new proxy that is identical to this proxy, except for the endpoint selection policy.
 284    /// </summary>
 285    /// <param name="newType">The new endpoint selection policy.</param>
 286    /// <returns>The new proxy with the specified endpoint selection policy.</returns>
 287    ObjectPrx ice_endpointSelection(EndpointSelectionType newType);
 288
 289    /// <summary>
 290    /// Creates a new proxy that is identical to this proxy, except for the encoding used to marshal
 291    /// parameters.
 292    /// </summary>
 293    /// <param name="encodingVersion">The encoding version to use to marshal request parameters.</param>
 294    /// <returns>The new proxy with the specified encoding version.</returns>
 295    ObjectPrx ice_encodingVersion(EncodingVersion encodingVersion);
 296
 297    /// <summary>
 298    /// Gets the encoding version used to marshal request parameters.
 299    /// </summary>
 300    /// <returns>The encoding version.</returns>
 301    EncodingVersion ice_getEncodingVersion();
 302
 303    /// <summary>
 304    /// Gets the router for this proxy.
 305    /// </summary>
 306    /// <returns>The router for the proxy. If no router is configured for the proxy, the return value
 307    /// is null.</returns>
 308    RouterPrx? ice_getRouter();
 309
 310    /// <summary>
 311    /// Creates a new proxy that is identical to this proxy, except for the router.
 312    /// </summary>
 313    /// <param name="router">The router for the new proxy.</param>
 314    /// <returns>The new proxy with the specified router.</returns>
 315    ObjectPrx ice_router(RouterPrx? router);
 316
 317    /// <summary>
 318    /// Gets the locator for this proxy.
 319    /// </summary>
 320    /// <returns>The locator for this proxy. If no locator is configured, the return value is null.</returns>
 321    LocatorPrx? ice_getLocator();
 322
 323    /// <summary>
 324    /// Creates a new proxy that is identical to this proxy, except for the locator.
 325    /// </summary>
 326    /// <param name="locator">The locator for the new proxy.</param>
 327    /// <returns>The new proxy with the specified locator.</returns>
 328    ObjectPrx ice_locator(LocatorPrx? locator);
 329
 330    /// <summary>
 331    /// Returns whether this proxy has collocation optimization enabled.
 332    /// </summary>
 333    /// <returns><see langword="true"/> if this proxy has collocation optimization enabled; otherwise,
 334    /// <see langword="false"/>.</returns>
 335    /// <seealso cref="ice_collocationOptimized(bool)"/>
 336    bool ice_isCollocationOptimized();
 337
 338    /// <summary>
 339    /// Creates a new proxy that is identical to this proxy, except for collocation optimization.
 340    /// </summary>
 341    /// <param name="collocated"><see langword="true"/> if the new proxy enables collocation optimization; otherwise,
 342    /// <see langword="false"/>.</param>
 343    /// <returns>The new proxy with the specified collocation optimization.</returns>
 344    ObjectPrx ice_collocationOptimized(bool collocated);
 345
 346    /// <summary>
 347    /// Creates a new proxy that is identical to this proxy, but uses twoway invocations.
 348    /// </summary>
 349    /// <returns>A new proxy that uses twoway invocations.</returns>
 350    ObjectPrx ice_twoway();
 351
 352    /// <summary>
 353    /// Returns whether this proxy uses twoway invocations.
 354    /// </summary>
 355    /// <returns><see langword="true"/> if this proxy uses twoway invocations; otherwise,
 356    /// <see langword="false"/>.</returns>
 357    bool ice_isTwoway();
 358
 359    /// <summary>
 360    /// Creates a new proxy that is identical to this proxy, but uses oneway invocations.
 361    /// </summary>
 362    /// <returns>A new proxy that uses oneway invocations.</returns>
 363    ObjectPrx ice_oneway();
 364
 365    /// <summary>
 366    /// Returns whether this proxy uses oneway invocations.
 367    /// </summary>
 368    /// <returns><see langword="true"/> if this proxy uses oneway invocations; otherwise,
 369    /// <see langword="false"/>.</returns>
 370    bool ice_isOneway();
 371
 372    /// <summary>
 373    /// Creates a new proxy that is identical to this proxy, but uses batch oneway invocations.
 374    /// </summary>
 375    /// <returns>A new proxy that uses batch oneway invocations.</returns>
 376    ObjectPrx ice_batchOneway();
 377
 378    /// <summary>
 379    /// Returns whether this proxy uses batch oneway invocations.
 380    /// </summary>
 381    /// <returns><see langword="true"/> if this proxy uses batch oneway invocations; otherwise,
 382    /// <see langword="false"/>.</returns>
 383    bool ice_isBatchOneway();
 384
 385    /// <summary>
 386    /// Creates a new proxy that is identical to this proxy, but uses datagram invocations.
 387    /// </summary>
 388    /// <returns>A new proxy that uses datagram invocations.</returns>
 389    ObjectPrx ice_datagram();
 390
 391    /// <summary>
 392    /// Returns whether this proxy uses datagram invocations.
 393    /// </summary>
 394    /// <returns><see langword="true"/> if this proxy uses datagram invocations; otherwise,
 395    /// <see langword="false"/>.</returns>
 396    bool ice_isDatagram();
 397
 398    /// <summary>
 399    /// Creates a new proxy that is identical to this proxy, but uses batch datagram invocations.
 400    /// </summary>
 401    /// <returns>A new proxy that uses batch datagram invocations.</returns>
 402    ObjectPrx ice_batchDatagram();
 403
 404    /// <summary>
 405    /// Returns whether this proxy uses batch datagram invocations.
 406    /// </summary>
 407    /// <returns><see langword="true"/> if this proxy uses batch datagram invocations; otherwise,
 408    /// <see langword="false"/>.</returns>
 409    bool ice_isBatchDatagram();
 410
 411    /// <summary>
 412    /// Creates a new proxy that is identical to this proxy, except for compression.
 413    /// </summary>
 414    /// <param name="compress"><see langword="true"/> enables compression for the new proxy;
 415    /// <see langword="false"/> disables compression.</param>
 416    /// <returns>A new proxy with the specified compression setting.</returns>
 417    ObjectPrx ice_compress(bool compress);
 418
 419    /// <summary>
 420    /// Gets the compression override setting of this proxy.
 421    /// </summary>
 422    /// <returns>The compression override setting, or <see langword="null"/> if no override is set. When set, it's
 423    /// <see langword="true"/> if compression is enabled; otherwise, <see langword="false"/>.</returns>
 424    bool? ice_getCompress();
 425
 426    /// <summary>
 427    /// Creates a new proxy that is identical to this proxy, except for its connection ID.
 428    /// </summary>
 429    /// <param name="connectionId">The connection ID for the new proxy. An empty string removes the
 430    /// connection ID.</param>
 431    /// <returns>A new proxy with the specified connection ID.</returns>
 432    ObjectPrx ice_connectionId(string connectionId);
 433
 434    /// <summary>
 435    /// Gets the connection id of this proxy.
 436    /// </summary>
 437    /// <returns>The connection id.</returns>
 438    string ice_getConnectionId();
 439
 440    /// <summary>
 441    /// Returns a proxy that is identical to this proxy, except it's a fixed proxy bound
 442    /// to the given connection.
 443    /// </summary>
 444    /// <param name="connection">The fixed proxy connection.</param>
 445    /// <returns>A fixed proxy bound to the given connection.</returns>
 446    ObjectPrx ice_fixed(Ice.Connection connection);
 447
 448    /// <summary>
 449    /// Returns whether this proxy is a fixed proxy.
 450    /// </summary>
 451    /// <returns><see langword="true"/> if this is a fixed proxy; otherwise, <see langword="false"/>.</returns>
 452    bool ice_isFixed();
 453
 454    /// <summary>
 455    /// Gets the connection to the server that hosts the target object. This method establishes a new connection to
 456    /// the server if the connection is not already established, or if the previously established connection is
 457    /// closed or being closed. For a fixed proxy, this method returns the connection this proxy is bound to, even
 458    /// when this connection is closed.
 459    /// </summary>
 460    /// <returns>The connection to the server that hosts the target object, or null when this proxy uses collocation
 461    /// optimization to communicate with the target object.</returns>
 462    Connection? ice_getConnection();
 463
 464    /// <summary>
 465    /// Gets the connection to the server that hosts the target object. This method establishes a new connection to
 466    /// the server if the connection is not already established, or if the previously established connection is
 467    /// closed or being closed. For a fixed proxy, this method returns the connection this proxy is bound to, even
 468    /// when this connection is closed.
 469    /// </summary>
 470    /// <param name="progress">Sent progress provider.</param>
 471    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 472    /// <returns>The connection to the server that hosts the target object, or null when this proxy uses collocation
 473    /// optimization to communicate with the target object.</returns>
 474    Task<Connection?> ice_getConnectionAsync(IProgress<bool>? progress = null, CancellationToken cancel = default);
 475
 476    /// <summary>
 477    /// Gets the cached <see cref="Connection"/> for this proxy. Once this proxy has been associated with a
 478    /// connection (typically during its first invocation), it caches this connection and continues using it for
 479    /// subsequent invocations, until an invocation on this proxy fails. This method never attempts to establish a
 480    /// connection. For a fixed proxy, this method returns the connection this proxy is bound to, even when this
 481    /// connection is closed. This method never throws.
 482    /// </summary>
 483    /// <returns>The cached connection, or null if this proxy doesn't have a cached connection. The returned
 484    /// connection can be closed.</returns>
 485    /// <remarks>A proxy with connection caching disabled (see <see cref="ice_connectionCached(bool)"/>) never caches
 486    /// a connection: for such a proxy, this method always returns null. This method also returns null when this
 487    /// proxy reaches its target object through collocation optimization (see
 488    /// <see cref="ice_collocationOptimized(bool)"/>): collocated invocations don't use a connection.</remarks>
 489    Connection? ice_getCachedConnection();
 490
 491    /// <summary>
 492    /// Flushes any pending batched requests for this proxy. The call blocks until the flush is complete.
 493    /// </summary>
 494    void ice_flushBatchRequests();
 495
 496    /// <summary>
 497    /// Asynchronously flushes any pending batched requests for this proxy.
 498    /// </summary>
 499    /// <param name="progress">Sent progress provider.</param>
 500    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 501    /// <returns>The task object representing the asynchronous operation.</returns>
 502    Task ice_flushBatchRequestsAsync(
 503        IProgress<bool>? progress = null,
 504        CancellationToken cancel = default);
 505
 506    /// <summary>
 507    /// Write a proxy to the output stream.
 508    /// </summary>
 509    /// <param name="os">Output stream object to write the proxy.</param>
 510    [EditorBrowsable(EditorBrowsableState.Never)]
 511    void iceWrite(OutputStream os);
 512
 513    /// <summary>
 514    /// Returns a scheduler object that uses the Ice thread pool.
 515    /// </summary>
 516    /// <returns>The task scheduler object.</returns>
 517    TaskScheduler ice_scheduler();
 518
 519    /// <summary>
 520    /// Ensures that a proxy received over the wire is not null.
 521    /// </summary>
 522    /// <param name="proxy">The proxy to check.</param>
 523    /// <param name="current">The current object of the corresponding incoming request.</param>
 524    /// <exception cref="MarshalException">Thrown when the proxy is null.</exception>
 525    static void checkNotNull(ObjectPrx? proxy, Current current)
 526    {
 527        if (proxy is null)
 528        {
 529            throw new MarshalException(
 530                $"Null proxy passed to '{current.operation}' on object '{current.adapter.getCommunicator().identityToStr
 531        }
 532    }
 533}
 534
 535/// <summary>
 536/// Represent the result of the ice_invokeAsync operation.
 537/// </summary>
 538public record struct Object_Ice_invokeResult(bool returnValue, byte[] outEncaps);
 539
 540/// <summary>
 541/// Base class of all object proxies.
 542/// </summary>
 543public abstract class ObjectPrxHelperBase : ObjectPrx
 544{
 545    public static bool operator ==(ObjectPrxHelperBase? lhs, ObjectPrxHelperBase? rhs) =>
 546        lhs is not null ? lhs.Equals(rhs) : rhs is null;
 547
 548    public static bool operator !=(ObjectPrxHelperBase? lhs, ObjectPrxHelperBase? rhs) => !(lhs == rhs);
 549
 550    /// <summary>
 551    /// Returns whether this proxy equals the passed object. Two proxies are equal if they are equal in all
 552    /// respects, that is, if their object identity, endpoints, timeout settings, and so on are all equal.
 553    /// </summary>
 554    /// <param name="other">The proxy to compare this proxy with.</param>
 555    /// <returns><see langword="true"/> if this proxy is equal to <paramref name="other"/>; otherwise,
 556    /// <see langword="false"/>.</returns>
 557    public bool Equals(ObjectPrx? other) =>
 558        other is not null && _reference == ((ObjectPrxHelperBase)other)._reference;
 559
 560    public override bool Equals(object? obj) => Equals(obj as ObjectPrx);
 561
 562    /// <summary>
 563    /// Returns a hash code for this proxy.
 564    /// </summary>
 565    /// <returns>The hash code.</returns>
 566    public override int GetHashCode() => _reference.GetHashCode();
 567
 568    /// <summary>
 569    /// Gets the communicator that created this proxy.
 570    /// </summary>
 571    /// <returns>The communicator that created this proxy.</returns>
 572    public Communicator ice_getCommunicator() => _reference.getCommunicator();
 573
 574    /// <summary>
 575    /// Gets the stringified form of this proxy.
 576    /// </summary>
 577    /// <returns>The stringified proxy.</returns>
 578    public override string ToString() => _reference.ToString();
 579
 580    /// <summary>
 581    /// Tests whether this object supports a specific Slice interface.
 582    /// </summary>
 583    /// <param name="id">The type ID of the Slice interface to test against.</param>
 584    /// <param name="context">The request context.</param>
 585    /// <returns><see langword="true"/> if the target object has the interface specified by id or derives
 586    /// from the interface specified by id.</returns>
 587    public bool ice_isA(string id, Dictionary<string, string>? context = null)
 588    {
 589        try
 590        {
 591            return iceI_ice_isAAsync(id, context, synchronous: true, progress: null, CancellationToken.None).Result;
 592        }
 593        catch (AggregateException ex)
 594        {
 595            throw ex.InnerException!;
 596        }
 597    }
 598
 599    /// <summary>
 600    /// Tests whether this object supports a specific Slice interface.
 601    /// </summary>
 602    /// <param name="id">The type ID of the Slice interface to test against.</param>
 603    /// <param name="context">The request context.</param>
 604    /// <param name="progress">Sent progress provider.</param>
 605    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 606    /// <returns>The task object representing the asynchronous operation.</returns>
 607    public Task<bool> ice_isAAsync(
 608        string id,
 609        Dictionary<string, string>? context = null,
 610        IProgress<bool>? progress = null,
 611        CancellationToken cancel = default) => iceI_ice_isAAsync(id, context, synchronous: false, progress, cancel);
 612
 613    private Task<bool>
 614    iceI_ice_isAAsync(
 615        string id,
 616        Dictionary<string, string>? context,
 617        bool synchronous,
 618        IProgress<bool>? progress,
 619        CancellationToken cancel)
 620    {
 621        iceCheckTwowayOnly(_ice_isA_name);
 622        var completed = new OperationTaskCompletionCallback<bool>(progress, cancel);
 623        iceI_ice_isA(id, context, completed, synchronous);
 624        return completed.Task;
 625    }
 626
 627    private const string _ice_isA_name = "ice_isA";
 628
 629    private void iceI_ice_isA(
 630        string id,
 631        Dictionary<string, string>? context,
 632        OutgoingAsyncCompletionCallback completed,
 633        bool synchronous)
 634    {
 635        getOutgoingAsync<bool>(completed).invoke(
 636            _ice_isA_name,
 637            OperationMode.Idempotent,
 638            FormatType.CompactFormat,
 639            context,
 640            synchronous,
 641            (OutputStream os) => os.writeString(id),
 642            null,
 643            (InputStream iss) => iss.readBool());
 644    }
 645
 646    /// <summary>
 647    /// Tests whether the target object of this proxy can be reached.
 648    /// </summary>
 649    /// <param name="context">The request context.</param>
 650    public void ice_ping(Dictionary<string, string>? context = null)
 651    {
 652        try
 653        {
 654            iceI_ice_pingAsync(context, synchronous: true, progress: null, CancellationToken.None).Wait();
 655        }
 656        catch (AggregateException ex)
 657        {
 658            throw ex.InnerException!;
 659        }
 660    }
 661
 662    /// <summary>
 663    /// Tests whether the target object of this proxy can be reached.
 664    /// </summary>
 665    /// <param name="context">The request context.</param>
 666    /// <param name="progress">Sent progress provider.</param>
 667    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 668    /// <returns>The task object representing the asynchronous operation.</returns>
 669    public Task ice_pingAsync(
 670        Dictionary<string, string>? context = null,
 671        IProgress<bool>? progress = null,
 672        CancellationToken cancel = default) => iceI_ice_pingAsync(context, synchronous: false, progress, cancel);
 673
 674    private Task
 675    iceI_ice_pingAsync(
 676        Dictionary<string, string>? context,
 677        bool synchronous,
 678        IProgress<bool>? progress,
 679        CancellationToken cancel)
 680    {
 681        var completed = new OperationTaskCompletionCallback<object>(progress, cancel);
 682        iceI_ice_ping(context, completed, synchronous);
 683        return completed.Task;
 684    }
 685
 686    private const string _ice_ping_name = "ice_ping";
 687
 688    private void iceI_ice_ping(
 689        Dictionary<string, string>? context,
 690        OutgoingAsyncCompletionCallback completed,
 691        bool synchronous)
 692    {
 693        getOutgoingAsync<object>(completed).invoke(
 694            _ice_ping_name,
 695            OperationMode.Idempotent,
 696            FormatType.CompactFormat,
 697            context,
 698            synchronous);
 699    }
 700
 701    /// <summary>
 702    /// Gets the Slice type IDs of the interfaces supported by the target object of this proxy.
 703    /// </summary>
 704    /// <param name="context">The request context.</param>
 705    /// <returns>The Slice type IDs of the interfaces supported by the target object, in alphabetical order.</returns>
 706    public string[] ice_ids(Dictionary<string, string>? context = null)
 707    {
 708        try
 709        {
 710            return iceI_ice_idsAsync(context, synchronous: true, progress: null, CancellationToken.None).Result;
 711        }
 712        catch (AggregateException ex)
 713        {
 714            throw ex.InnerException!;
 715        }
 716    }
 717
 718    /// <summary>
 719    /// Gets the Slice type IDs of the interfaces supported by the target object of this proxy.
 720    /// </summary>
 721    /// <param name="context">The request context.</param>
 722    /// <param name="progress">Sent progress provider.</param>
 723    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 724    /// <returns>The task object representing the asynchronous operation.</returns>
 725    public Task<string[]>
 726    ice_idsAsync(
 727        Dictionary<string, string>? context = null,
 728        IProgress<bool>? progress = null,
 729        CancellationToken cancel = default) => iceI_ice_idsAsync(context, synchronous: false, progress, cancel);
 730
 731    private Task<string[]> iceI_ice_idsAsync(
 732        Dictionary<string, string>? context,
 733        bool synchronous,
 734        IProgress<bool>? progress,
 735        CancellationToken cancel)
 736    {
 737        iceCheckTwowayOnly(_ice_ids_name);
 738        var completed = new OperationTaskCompletionCallback<string[]>(progress, cancel);
 739        iceI_ice_ids(context, completed, synchronous);
 740        return completed.Task;
 741    }
 742
 743    private const string _ice_ids_name = "ice_ids";
 744
 745    private void iceI_ice_ids(
 746        Dictionary<string, string>? context,
 747        OutgoingAsyncCompletionCallback completed,
 748        bool synchronous)
 749    {
 750        getOutgoingAsync<string[]>(completed).invoke(
 751            _ice_ids_name,
 752            OperationMode.Idempotent,
 753            FormatType.CompactFormat,
 754            context,
 755            synchronous,
 756            read: (InputStream iss) => iss.readStringSeq());
 757    }
 758
 759    /// <summary>
 760    /// Gets the Slice type ID of the most-derived interface supported by the target object of this proxy.
 761    /// </summary>
 762    /// <param name="context">The request context.</param>
 763    /// <returns>The Slice type ID of the most-derived interface.</returns>
 764    public string ice_id(Dictionary<string, string>? context = null)
 765    {
 766        try
 767        {
 768            return iceI_ice_idAsync(context, synchronous: true, progress: null, CancellationToken.None).Result;
 769        }
 770        catch (AggregateException ex)
 771        {
 772            throw ex.InnerException!;
 773        }
 774    }
 775
 776    /// <summary>
 777    /// Gets the Slice type ID of the most-derived interface supported by the target object of this proxy.
 778    /// </summary>
 779    /// <param name="context">The request context.</param>
 780    /// <param name="progress">Sent progress provider.</param>
 781    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 782    /// <returns>The task object representing the asynchronous operation.</returns>
 783    public Task<string> ice_idAsync(
 784        Dictionary<string, string>? context = null,
 785        IProgress<bool>? progress = null,
 786        CancellationToken cancel = default) => iceI_ice_idAsync(context, synchronous: false, progress, cancel);
 787
 788    private Task<string>
 789    iceI_ice_idAsync(
 790        Dictionary<string, string>? context,
 791        bool synchronous,
 792        IProgress<bool>? progress,
 793        CancellationToken cancel)
 794    {
 795        iceCheckTwowayOnly(_ice_id_name);
 796        var completed = new OperationTaskCompletionCallback<string>(progress, cancel);
 797        iceI_ice_id(context, completed, synchronous);
 798        return completed.Task;
 799    }
 800
 801    private const string _ice_id_name = "ice_id";
 802
 803    private void iceI_ice_id(
 804        Dictionary<string, string>? context,
 805        OutgoingAsyncCompletionCallback completed,
 806        bool synchronous)
 807    {
 808        getOutgoingAsync<string>(completed).invoke(
 809            _ice_id_name,
 810            OperationMode.Idempotent,
 811            FormatType.CompactFormat,
 812            context,
 813            synchronous,
 814            read: (InputStream iss) => iss.readString());
 815    }
 816
 817    /// <summary>
 818    /// Invokes an operation dynamically.
 819    /// </summary>
 820    /// <param name="operation">The name of the operation to invoke.</param>
 821    /// <param name="mode">The operation mode (normal or idempotent).</param>
 822    /// <param name="inEncaps">The encoded in-parameters for the operation. You can pass an empty byte array when the
 823    /// operation takes no in-parameters; the Ice runtime then marshals an empty encapsulation.</param>
 824    /// <param name="outEncaps">The encoded out-parameters and return value
 825    /// for the operation. The return value follows any out-parameters.</param>
 826    /// <param name="context">The request context.</param>
 827    /// <returns>If the operation completed successfully, the return value is <see langword="true"/>.
 828    /// If the operation raises a user exception, the return value is <see langword="false"/>; in this case,
 829    /// <paramref name="outEncaps"/> contains the encoded user exception.
 830    /// If the operation raises a runtime exception, it throws it directly. When this proxy is a oneway, datagram, or
 831    /// batch proxy, the return value is always <see langword="true"/> and <paramref name="outEncaps"/> is
 832    /// empty.</returns>
 833    public bool ice_invoke(
 834        string operation,
 835        OperationMode mode,
 836        byte[] inEncaps,
 837        out byte[] outEncaps,
 838        Dictionary<string, string>? context = null)
 839    {
 840        try
 841        {
 842            Object_Ice_invokeResult result = iceI_ice_invokeAsync(
 843                operation,
 844                mode,
 845                inEncaps,
 846                context,
 847                synchronous: true,
 848                progress: null,
 849                CancellationToken.None).Result;
 850            outEncaps = result.outEncaps;
 851            return result.returnValue;
 852        }
 853        catch (AggregateException ex)
 854        {
 855            throw ex.InnerException!;
 856        }
 857    }
 858
 859    /// <summary>
 860    /// Invokes an operation dynamically.
 861    /// </summary>
 862    /// <param name="operation">The name of the operation to invoke.</param>
 863    /// <param name="mode">The operation mode (normal or idempotent).</param>
 864    /// <param name="inEncaps">The encoded in-parameters for the operation. You can pass an empty byte array when the
 865    /// operation takes no in-parameters; the Ice runtime then marshals an empty encapsulation.</param>
 866    /// <param name="context">The request context.</param>
 867    /// <param name="progress">Sent progress provider.</param>
 868    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 869    /// <returns>The task object representing the asynchronous operation. When this proxy is a oneway, datagram, or
 870    /// batch proxy, the task completes with <c>returnValue</c> set to <see langword="true"/> and an empty
 871    /// <c>outEncaps</c>.</returns>
 872    public Task<Object_Ice_invokeResult>
 873    ice_invokeAsync(
 874        string operation,
 875        OperationMode mode,
 876        byte[] inEncaps,
 877        Dictionary<string, string>? context = null,
 878        IProgress<bool>? progress = null,
 879        CancellationToken cancel = default) =>
 880            iceI_ice_invokeAsync(operation, mode, inEncaps, context, synchronous: false, progress, cancel);
 881
 882    private Task<Object_Ice_invokeResult>
 883    iceI_ice_invokeAsync(
 884        string operation,
 885        OperationMode mode,
 886        byte[] inEncaps,
 887        Dictionary<string, string>? context,
 888        bool synchronous,
 889        IProgress<bool>? progress,
 890        CancellationToken cancel)
 891    {
 892        var completed = new InvokeTaskCompletionCallback(progress, cancel);
 893        iceI_ice_invoke(operation, mode, inEncaps, context, completed, synchronous);
 894        return completed.Task;
 895    }
 896
 897    private void iceI_ice_invoke(
 898        string operation,
 899        OperationMode mode,
 900        byte[] inEncaps,
 901        Dictionary<string, string>? context,
 902        OutgoingAsyncCompletionCallback completed,
 903        bool synchronous) => getInvokeOutgoingAsync(completed).invoke(operation, mode, inEncaps, context, synchronous);
 904
 905    /// <summary>
 906    /// Gets the identity embedded in this proxy.
 907    /// </summary>
 908    /// <returns>The identity of the target object.</returns>
 909    public Identity ice_getIdentity() => _reference.getIdentity() with { };
 910
 911    /// <summary>
 912    /// Creates a new proxy that is identical to this proxy, except for the proxy identity.
 913    /// </summary>
 914    /// <param name="newIdentity">The identity for the new proxy.</param>
 915    /// <returns>The new proxy with the specified identity.</returns>
 916    /// <exception cref="ArgumentException">If the name of the new identity is empty.</exception>
 917    public ObjectPrx ice_identity(Identity newIdentity)
 918    {
 919        if (newIdentity.name.Length == 0)
 920        {
 921            throw new ArgumentException("The name of an Ice object identity cannot be empty.", nameof(newIdentity));
 922        }
 923        if (newIdentity == _reference.getIdentity())
 924        {
 925            return this;
 926        }
 927        else
 928        {
 929            return new ObjectPrxHelper(_reference.changeIdentity(newIdentity));
 930        }
 931    }
 932
 933    /// <summary>
 934    /// Gets the per-proxy context for this proxy.
 935    /// </summary>
 936    /// <returns>A copy of the per-proxy context. The dictionary is empty when this proxy has no per-proxy
 937    /// context.</returns>
 938    public Dictionary<string, string> ice_getContext() => new Dictionary<string, string>(_reference.getContext());
 939
 940    /// <summary>
 941    /// Creates a new proxy that is identical to this proxy, except for the per-proxy context.
 942    /// </summary>
 943    /// <param name="newContext">The context for the new proxy.</param>
 944    /// <returns>The proxy with the new per-proxy context.</returns>
 945    public ObjectPrx ice_context(Dictionary<string, string> newContext) =>
 946        iceNewInstance(_reference.changeContext(newContext));
 947
 948    /// <summary>
 949    /// Gets the facet for this proxy.
 950    /// </summary>
 951    /// <returns>The facet for this proxy. If the proxy uses the default facet, the return value is the
 952    /// empty string.</returns>
 953    public string ice_getFacet() => _reference.getFacet();
 954
 955    /// <summary>
 956    /// Creates a new proxy that is identical to this proxy, except for the facet.
 957    /// </summary>
 958    /// <param name="newFacet">The facet for the new proxy.</param>
 959    /// <returns>The proxy with the new facet.</returns>
 960    public ObjectPrx ice_facet(string newFacet)
 961    {
 962        newFacet ??= "";
 963
 964        if (newFacet == _reference.getFacet())
 965        {
 966            return this;
 967        }
 968        else
 969        {
 970            return new ObjectPrxHelper(_reference.changeFacet(newFacet));
 971        }
 972    }
 973
 974    /// <summary>
 975    /// Gets the adapter ID for this proxy.
 976    /// </summary>
 977    /// <returns>The adapter ID. If the proxy does not have an adapter ID, the return value is the
 978    /// empty string.</returns>
 979    public string ice_getAdapterId() => _reference.getAdapterId();
 980
 981    /// <summary>
 982    /// Creates a new proxy that is identical to this proxy, except for the adapter ID.
 983    /// </summary>
 984    /// <param name="newAdapterId">The adapter ID for the new proxy.</param>
 985    /// <returns>The new proxy with the specified adapter ID.</returns>
 986    public ObjectPrx ice_adapterId(string newAdapterId)
 987    {
 988        newAdapterId ??= "";
 989
 990        if (newAdapterId == _reference.getAdapterId())
 991        {
 992            return this;
 993        }
 994        else
 995        {
 996            return iceNewInstance(_reference.changeAdapterId(newAdapterId));
 997        }
 998    }
 999
 1000    /// <summary>
 1001    /// Gets the endpoints used by this proxy.
 1002    /// </summary>
 1003    /// <returns>The endpoints used by this proxy.</returns>
 1004    public Endpoint[] ice_getEndpoints() => (Endpoint[])_reference.getEndpoints().Clone();
 1005
 1006    /// <summary>
 1007    /// Creates a new proxy that is identical to this proxy, except for the endpoints.
 1008    /// </summary>
 1009    /// <param name="newEndpoints">The endpoints for the new proxy.</param>
 1010    /// <returns>The new proxy with the specified endpoints.</returns>
 1011    public ObjectPrx ice_endpoints(Endpoint[] newEndpoints)
 1012    {
 1013        newEndpoints ??= [];
 1014
 1015        if (_reference.getEndpoints().SequenceEqual(newEndpoints))
 1016        {
 1017            return this;
 1018        }
 1019        else
 1020        {
 1021            var endpoints = new EndpointI[newEndpoints.Length];
 1022            for (int i = 0; i < newEndpoints.Length; ++i)
 1023            {
 1024                endpoints[i] = (EndpointI)newEndpoints[i];
 1025            }
 1026            return iceNewInstance(_reference.changeEndpoints(endpoints));
 1027        }
 1028    }
 1029
 1030    /// <summary>
 1031    /// Gets the locator cache timeout of this proxy.
 1032    /// </summary>
 1033    /// <returns>The locator cache timeout value.</returns>
 1034    public TimeSpan ice_getLocatorCacheTimeout() => _reference.getLocatorCacheTimeout();
 1035
 1036    /// <summary>
 1037    /// Creates a new proxy that is identical to this proxy, except for the locator cache timeout.
 1038    /// </summary>
 1039    /// <param name="newTimeout">The new locator cache timeout (in seconds). Any negative value means infinite
 1040    /// and is normalized to -1.</param>
 1041    /// <returns>The new proxy with the specified locator cache timeout.</returns>
 1042    public ObjectPrx ice_locatorCacheTimeout(int newTimeout) =>
 1043        ice_locatorCacheTimeout(TimeSpan.FromSeconds(newTimeout));
 1044
 1045    /// <summary>
 1046    /// Creates a new proxy that is identical to this proxy, except for the locator cache timeout.
 1047    /// </summary>
 1048    /// <param name="newTimeout">The new locator cache timeout. Any negative timeout means infinite and is
 1049    /// normalized to -1 second; a timeout that is not a whole number of seconds is rounded up to the next whole
 1050    /// number of seconds.</param>
 1051    /// <returns>The new proxy with the specified locator cache timeout.</returns>
 1052    /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="newTimeout"/> is greater than
 1053    /// <see cref="int.MaxValue"/> seconds.</exception>
 1054    public ObjectPrx ice_locatorCacheTimeout(TimeSpan newTimeout)
 1055    {
 1056        if (newTimeout < TimeSpan.Zero)
 1057        {
 1058            newTimeout = TimeSpan.FromSeconds(-1);
 1059        }
 1060        else
 1061        {
 1062            // The limit is a whole number of seconds, so a timeout that passes this check still fits after
 1063            // rounding up.
 1064            if (newTimeout > TimeSpan.FromSeconds(int.MaxValue))
 1065            {
 1066                throw new ArgumentOutOfRangeException(
 1067                    nameof(newTimeout),
 1068                    $"The locator cache timeout cannot be greater than {int.MaxValue} seconds.");
 1069            }
 1070            newTimeout = roundUp(newTimeout, TimeSpan.TicksPerSecond);
 1071        }
 1072
 1073        if (newTimeout == _reference.getLocatorCacheTimeout())
 1074        {
 1075            return this;
 1076        }
 1077        else
 1078        {
 1079            return iceNewInstance(_reference.changeLocatorCacheTimeout(newTimeout));
 1080        }
 1081    }
 1082
 1083    /// <summary>
 1084    /// Gets the invocation timeout of this proxy.
 1085    /// </summary>
 1086    /// <returns>The invocation timeout value.</returns>
 1087    public TimeSpan ice_getInvocationTimeout() => _reference.getInvocationTimeout();
 1088
 1089    /// <summary>
 1090    /// Creates a new proxy that is identical to this proxy, except for the invocation timeout.
 1091    /// </summary>
 1092    /// <param name="newTimeout">The new invocation timeout (in milliseconds). Zero or any negative value means
 1093    /// infinite and is normalized to -1.</param>
 1094    /// <returns>The new proxy with the specified invocation timeout.</returns>
 1095    public ObjectPrx ice_invocationTimeout(int newTimeout) =>
 1096        ice_invocationTimeout(TimeSpan.FromMilliseconds(newTimeout));
 1097
 1098    /// <summary>
 1099    /// Creates a new proxy that is identical to this proxy, except for the invocation timeout.
 1100    /// </summary>
 1101    /// <param name="newTimeout">The new invocation timeout. Zero or any negative timeout means infinite and is
 1102    /// normalized to -1 millisecond; a timeout that is not a whole number of milliseconds is rounded up to the next
 1103    /// whole number of milliseconds.</param>
 1104    /// <returns>The new proxy with the specified invocation timeout.</returns>
 1105    /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="newTimeout"/> is greater than
 1106    /// <see cref="int.MaxValue"/> milliseconds.</exception>
 1107    public ObjectPrx ice_invocationTimeout(TimeSpan newTimeout)
 1108    {
 1109        if (newTimeout <= TimeSpan.Zero)
 1110        {
 1111            newTimeout = TimeSpan.FromMilliseconds(-1);
 1112        }
 1113        else
 1114        {
 1115            // The limit is a whole number of milliseconds, so a timeout that passes this check still fits after
 1116            // rounding up.
 1117            if (newTimeout > TimeSpan.FromMilliseconds(int.MaxValue))
 1118            {
 1119                throw new ArgumentOutOfRangeException(
 1120                    nameof(newTimeout),
 1121                    $"The invocation timeout cannot be greater than {int.MaxValue} milliseconds.");
 1122            }
 1123            newTimeout = roundUp(newTimeout, TimeSpan.TicksPerMillisecond);
 1124        }
 1125
 1126        if (newTimeout == _reference.getInvocationTimeout())
 1127        {
 1128            return this;
 1129        }
 1130        else
 1131        {
 1132            return iceNewInstance(_reference.changeInvocationTimeout(newTimeout));
 1133        }
 1134    }
 1135
 1136    /// <summary>
 1137    /// Returns whether this proxy caches connections.
 1138    /// </summary>
 1139    /// <returns><see langword="true"/> if this proxy caches connections; otherwise, <see langword="false"/>.</returns>
 1140    public bool ice_isConnectionCached() => _reference.getCacheConnection();
 1141
 1142    /// <summary>
 1143    /// Creates a new proxy that is identical to this proxy, except for connection caching.
 1144    /// </summary>
 1145    /// <param name="newCache"><see langword="true"/> if the new proxy should cache connections; otherwise,
 1146    /// <see langword="false"/>.</param>
 1147    /// <returns>The new proxy with the specified caching policy.</returns>
 1148    public ObjectPrx ice_connectionCached(bool newCache)
 1149    {
 1150        if (newCache == _reference.getCacheConnection())
 1151        {
 1152            return this;
 1153        }
 1154        else
 1155        {
 1156            return iceNewInstance(_reference.changeCacheConnection(newCache));
 1157        }
 1158    }
 1159
 1160    /// <summary>
 1161    /// Returns how this proxy selects endpoints (randomly or ordered).
 1162    /// </summary>
 1163    /// <returns>The endpoint selection policy.</returns>
 1164    public EndpointSelectionType ice_getEndpointSelection() => _reference.getEndpointSelection();
 1165
 1166    /// <summary>
 1167    /// Creates a new proxy that is identical to this proxy, except for the endpoint selection policy.
 1168    /// </summary>
 1169    /// <param name="newType">The new endpoint selection policy.</param>
 1170    /// <returns>The new proxy with the specified endpoint selection policy.</returns>
 1171    public ObjectPrx ice_endpointSelection(EndpointSelectionType newType)
 1172    {
 1173        if (newType == _reference.getEndpointSelection())
 1174        {
 1175            return this;
 1176        }
 1177        else
 1178        {
 1179            return iceNewInstance(_reference.changeEndpointSelection(newType));
 1180        }
 1181    }
 1182
 1183    /// <summary>
 1184    /// Creates a new proxy that is identical to this proxy, except for the encoding used to marshal
 1185    /// parameters.
 1186    /// </summary>
 1187    /// <param name="encodingVersion">The encoding version to use to marshal request parameters.</param>
 1188    /// <returns>The new proxy with the specified encoding version.</returns>
 1189    public ObjectPrx ice_encodingVersion(EncodingVersion encodingVersion)
 1190    {
 1191        if (encodingVersion == _reference.getEncoding())
 1192        {
 1193            return this;
 1194        }
 1195        else
 1196        {
 1197            return iceNewInstance(_reference.changeEncoding(encodingVersion));
 1198        }
 1199    }
 1200
 1201    /// <summary>
 1202    /// Gets the encoding version used to marshal request parameters.
 1203    /// </summary>
 1204    /// <returns>The encoding version.</returns>
 1205    public EncodingVersion ice_getEncodingVersion() => _reference.getEncoding();
 1206
 1207    /// <summary>
 1208    /// Gets the router for this proxy.
 1209    /// </summary>
 1210    /// <returns>The router for the proxy. If no router is configured for the proxy, the return value
 1211    /// is null.</returns>
 1212    public RouterPrx? ice_getRouter()
 1213    {
 1214        RouterInfo ri = _reference.getRouterInfo();
 1215        return ri?.getRouter();
 1216    }
 1217
 1218    /// <summary>
 1219    /// Creates a new proxy that is identical to this proxy, except for the router.
 1220    /// </summary>
 1221    /// <param name="router">The router for the new proxy.</param>
 1222    /// <returns>The new proxy with the specified router.</returns>
 1223    public ObjectPrx ice_router(RouterPrx? router)
 1224    {
 1225        if (router == _reference.getRouterInfo()?.getRouter())
 1226        {
 1227            return this;
 1228        }
 1229        else
 1230        {
 1231            return iceNewInstance(_reference.changeRouter(router));
 1232        }
 1233    }
 1234
 1235    /// <summary>
 1236    /// Gets the locator for this proxy.
 1237    /// </summary>
 1238    /// <returns>The locator for this proxy. If no locator is configured, the return value is null.</returns>
 1239    public LocatorPrx? ice_getLocator()
 1240    {
 1241        LocatorInfo li = _reference.getLocatorInfo();
 1242        return li?.getLocator();
 1243    }
 1244
 1245    /// <summary>
 1246    /// Creates a new proxy that is identical to this proxy, except for the locator.
 1247    /// </summary>
 1248    /// <param name="locator">The locator for the new proxy.</param>
 1249    /// <returns>The new proxy with the specified locator.</returns>
 1250    public ObjectPrx ice_locator(LocatorPrx? locator)
 1251    {
 1252        if (locator == _reference.getLocatorInfo()?.getLocator())
 1253        {
 1254            return this;
 1255        }
 1256        else
 1257        {
 1258            return iceNewInstance(_reference.changeLocator(locator));
 1259        }
 1260    }
 1261
 1262    /// <summary>
 1263    /// Returns whether this proxy has collocation optimization enabled.
 1264    /// </summary>
 1265    /// <returns><see langword="true"/> if this proxy has collocation optimization enabled; otherwise,
 1266    /// <see langword="false"/>.</returns>
 1267    /// <seealso cref="ice_collocationOptimized(bool)"/>
 1268    public bool ice_isCollocationOptimized() => _reference.getCollocationOptimized();
 1269
 1270    /// <summary>
 1271    /// Creates a new proxy that is identical to this proxy, except for collocation optimization.
 1272    /// </summary>
 1273    /// <param name="collocated"><see langword="true"/> if the new proxy enables collocation optimization; otherwise,
 1274    /// <see langword="false"/>.</param>
 1275    /// <returns>The new proxy with the specified collocation optimization.</returns>
 1276    public ObjectPrx ice_collocationOptimized(bool collocated)
 1277    {
 1278        if (collocated == _reference.getCollocationOptimized())
 1279        {
 1280            return this;
 1281        }
 1282        else
 1283        {
 1284            return iceNewInstance(_reference.changeCollocationOptimized(collocated));
 1285        }
 1286    }
 1287
 1288    /// <summary>
 1289    /// Creates a new proxy that is identical to this proxy, but uses twoway invocations.
 1290    /// </summary>
 1291    /// <returns>A new proxy that uses twoway invocations.</returns>
 1292    public ObjectPrx ice_twoway()
 1293    {
 1294        if (_reference.isTwoway)
 1295        {
 1296            return this;
 1297        }
 1298        else
 1299        {
 1300            return iceNewInstance(_reference.changeMode(Reference.Mode.ModeTwoway));
 1301        }
 1302    }
 1303
 1304    /// <summary>
 1305    /// Returns whether this proxy uses twoway invocations.
 1306    /// </summary>
 1307    /// <returns><see langword="true"/> if this proxy uses twoway invocations; otherwise,
 1308    /// <see langword="false"/>.</returns>
 1309    public bool ice_isTwoway() => _reference.isTwoway;
 1310
 1311    /// <summary>
 1312    /// Creates a new proxy that is identical to this proxy, but uses oneway invocations.
 1313    /// </summary>
 1314    /// <returns>A new proxy that uses oneway invocations.</returns>
 1315    public ObjectPrx ice_oneway()
 1316    {
 1317        if (_reference.getMode() == Reference.Mode.ModeOneway)
 1318        {
 1319            return this;
 1320        }
 1321        else
 1322        {
 1323            return iceNewInstance(_reference.changeMode(Reference.Mode.ModeOneway));
 1324        }
 1325    }
 1326
 1327    /// <summary>
 1328    /// Returns whether this proxy uses oneway invocations.
 1329    /// </summary>
 1330    /// <returns><see langword="true"/> if this proxy uses oneway invocations; otherwise,
 1331    /// <see langword="false"/>.</returns>
 1332    public bool ice_isOneway() => _reference.getMode() == Reference.Mode.ModeOneway;
 1333
 1334    /// <summary>
 1335    /// Creates a new proxy that is identical to this proxy, but uses batch oneway invocations.
 1336    /// </summary>
 1337    /// <returns>A new proxy that uses batch oneway invocations.</returns>
 1338    public ObjectPrx ice_batchOneway()
 1339    {
 1340        if (_reference.getMode() == Reference.Mode.ModeBatchOneway)
 1341        {
 1342            return this;
 1343        }
 1344        else
 1345        {
 1346            return iceNewInstance(_reference.changeMode(Reference.Mode.ModeBatchOneway));
 1347        }
 1348    }
 1349
 1350    /// <summary>
 1351    /// Returns whether this proxy uses batch oneway invocations.
 1352    /// </summary>
 1353    /// <returns><see langword="true"/> if this proxy uses batch oneway invocations; otherwise,
 1354    /// <see langword="false"/>.</returns>
 1355    public bool ice_isBatchOneway() => _reference.getMode() == Reference.Mode.ModeBatchOneway;
 1356
 1357    /// <summary>
 1358    /// Creates a new proxy that is identical to this proxy, but uses datagram invocations.
 1359    /// </summary>
 1360    /// <returns>A new proxy that uses datagram invocations.</returns>
 1361    public ObjectPrx ice_datagram()
 1362    {
 1363        if (_reference.getMode() == Reference.Mode.ModeDatagram)
 1364        {
 1365            return this;
 1366        }
 1367        else
 1368        {
 1369            return iceNewInstance(_reference.changeMode(Reference.Mode.ModeDatagram));
 1370        }
 1371    }
 1372
 1373    /// <summary>
 1374    /// Returns whether this proxy uses datagram invocations.
 1375    /// </summary>
 1376    /// <returns><see langword="true"/> if this proxy uses datagram invocations; otherwise,
 1377    /// <see langword="false"/>.</returns>
 1378    public bool ice_isDatagram() => _reference.getMode() == Reference.Mode.ModeDatagram;
 1379
 1380    /// <summary>
 1381    /// Creates a new proxy that is identical to this proxy, but uses batch datagram invocations.
 1382    /// </summary>
 1383    /// <returns>A new proxy that uses batch datagram invocations.</returns>
 1384    public ObjectPrx ice_batchDatagram()
 1385    {
 1386        if (_reference.getMode() == Reference.Mode.ModeBatchDatagram)
 1387        {
 1388            return this;
 1389        }
 1390        else
 1391        {
 1392            return iceNewInstance(_reference.changeMode(Reference.Mode.ModeBatchDatagram));
 1393        }
 1394    }
 1395
 1396    /// <summary>
 1397    /// Returns whether this proxy uses batch datagram invocations.
 1398    /// </summary>
 1399    /// <returns><see langword="true"/> if this proxy uses batch datagram invocations; otherwise,
 1400    /// <see langword="false"/>.</returns>
 1401    public bool ice_isBatchDatagram() => _reference.getMode() == Reference.Mode.ModeBatchDatagram;
 1402
 1403    /// <summary>
 1404    /// Creates a new proxy that is identical to this proxy, except for compression.
 1405    /// </summary>
 1406    /// <param name="compress"><see langword="true"/> enables compression for the new proxy;
 1407    /// <see langword="false"/> disables compression.</param>
 1408    /// <returns>A new proxy with the specified compression setting.</returns>
 1409    public ObjectPrx ice_compress(bool compress)
 1410    {
 1411        if (compress == _reference.getCompress())
 1412        {
 1413            return this;
 1414        }
 1415        else
 1416        {
 1417            return iceNewInstance(_reference.changeCompress(compress));
 1418        }
 1419    }
 1420
 1421    /// <summary>
 1422    /// Obtains the compression override setting of this proxy.
 1423    /// </summary>
 1424    /// <returns>The compression override setting, or <see langword="null"/> if no override is set. When set, it's
 1425    /// <see langword="true"/> if compression is enabled; otherwise, <see langword="false"/>.</returns>
 1426    public bool? ice_getCompress() => _reference.getCompress();
 1427
 1428    /// <summary>
 1429    /// Creates a new proxy that is identical to this proxy, except for its connection ID.
 1430    /// </summary>
 1431    /// <param name="connectionId">The connection ID for the new proxy. An empty string removes the
 1432    /// connection ID.</param>
 1433    /// <returns>A new proxy with the specified connection ID.</returns>
 1434    public ObjectPrx ice_connectionId(string connectionId)
 1435    {
 1436        if (connectionId == _reference.getConnectionId())
 1437        {
 1438            return this;
 1439        }
 1440        else
 1441        {
 1442            return iceNewInstance(_reference.changeConnectionId(connectionId));
 1443        }
 1444    }
 1445
 1446    /// <summary>
 1447    /// Gets the connection id of this proxy.
 1448    /// </summary>
 1449    /// <returns>The connection id.</returns>
 1450    public string ice_getConnectionId() => _reference.getConnectionId();
 1451
 1452    /// <summary>
 1453    /// Returns a proxy that is identical to this proxy, except it's a fixed proxy bound
 1454    /// to the given connection.
 1455    /// </summary>
 1456    /// <param name="connection">The fixed proxy connection.</param>
 1457    /// <returns>A fixed proxy bound to the given connection.</returns>
 1458    public ObjectPrx ice_fixed(Ice.Connection connection)
 1459    {
 1460        if (connection is null)
 1461        {
 1462            throw new ArgumentException("invalid null connection passed to ice_fixed");
 1463        }
 1464        if (!(connection is Ice.ConnectionI))
 1465        {
 1466            throw new ArgumentException("invalid connection passed to ice_fixed");
 1467        }
 1468
 1469        if (connection == _reference.getConnection())
 1470        {
 1471            return this;
 1472        }
 1473        else
 1474        {
 1475            return iceNewInstance(_reference.changeConnection((Ice.ConnectionI)connection));
 1476        }
 1477    }
 1478
 1479    /// <summary>
 1480    /// Returns whether this proxy is a fixed proxy.
 1481    /// </summary>
 1482    /// <returns><see langword="true"/> if this is a fixed proxy; otherwise, <see langword="false"/>.</returns>
 1483    public bool ice_isFixed() => _reference is Ice.Internal.FixedReference;
 1484
 1485    public class GetConnectionTaskCompletionCallback : TaskCompletionCallback<Connection?>
 1486    {
 1487        public GetConnectionTaskCompletionCallback(
 1488            IProgress<bool>? progress = null,
 1489            CancellationToken cancellationToken = default)
 11490            : base(progress, cancellationToken)
 1491        {
 11492        }
 1493
 1494        public override void handleInvokeResponse(bool ok, OutgoingAsyncBase og) =>
 11495            SetResult(((ProxyGetConnection)og).getConnection());
 1496    }
 1497
 1498    public Connection? ice_getConnection()
 1499    {
 1500        // A fixed proxy is bound to a single connection: return this connection as is, whatever its state.
 1501        if (_reference is Ice.Internal.FixedReference)
 1502        {
 1503            return _reference.getConnection();
 1504        }
 1505        else
 1506        {
 1507            try
 1508            {
 1509                var completed = new GetConnectionTaskCompletionCallback();
 1510                iceI_ice_getConnection(completed, true);
 1511                return completed.Task.Result;
 1512            }
 1513            catch (AggregateException ex)
 1514            {
 1515                throw ex.InnerException!;
 1516            }
 1517        }
 1518    }
 1519
 1520    public Task<Connection?> ice_getConnectionAsync(IProgress<bool>? progress, CancellationToken cancel)
 1521    {
 1522        // A fixed proxy is bound to a single connection: return this connection as is, whatever its state.
 1523        if (_reference is Ice.Internal.FixedReference)
 1524        {
 1525            return Task.FromResult<Connection?>(_reference.getConnection());
 1526        }
 1527        else
 1528        {
 1529            var completed = new GetConnectionTaskCompletionCallback(progress, cancel);
 1530            iceI_ice_getConnection(completed, false);
 1531            return completed.Task;
 1532        }
 1533    }
 1534
 1535    private const string _ice_getConnection_name = "ice_getConnection";
 1536
 1537    private void iceI_ice_getConnection(OutgoingAsyncCompletionCallback completed, bool synchronous)
 1538    {
 1539        var outgoing = new ProxyGetConnection(this, completed);
 1540        outgoing.invoke(_ice_getConnection_name, synchronous);
 1541    }
 1542
 1543    /// <summary>
 1544    /// Gets the cached <see cref="Connection"/> for this proxy. Once this proxy has been associated with a
 1545    /// connection (typically during its first invocation), it caches this connection and continues using it for
 1546    /// subsequent invocations, until an invocation on this proxy fails. This method never attempts to establish a
 1547    /// connection. For a fixed proxy, this method returns the connection this proxy is bound to, even when this
 1548    /// connection is closed. This method never throws.
 1549    /// </summary>
 1550    /// <returns>The cached connection, or null if this proxy doesn't have a cached connection. The returned
 1551    /// connection can be closed.</returns>
 1552    /// <remarks>A proxy with connection caching disabled (see <see cref="ice_connectionCached(bool)"/>) never caches
 1553    /// a connection: for such a proxy, this method always returns null. This method also returns null when this
 1554    /// proxy reaches its target object through collocation optimization (see
 1555    /// <see cref="ice_collocationOptimized(bool)"/>): collocated invocations don't use a connection.</remarks>
 1556    public Connection? ice_getCachedConnection()
 1557    {
 1558        // A fixed proxy is bound to a single connection: return this connection as is, whatever its state.
 1559        if (_reference is Ice.Internal.FixedReference)
 1560        {
 1561            return _reference.getConnection();
 1562        }
 1563        else
 1564        {
 1565            return _requestHandlerCache.cachedConnection;
 1566        }
 1567    }
 1568
 1569    /// <summary>
 1570    /// Flushes any pending batched requests for this proxy. The call blocks until the flush is complete.
 1571    /// </summary>
 1572    public void ice_flushBatchRequests()
 1573    {
 1574        try
 1575        {
 1576            var completed = new FlushBatchTaskCompletionCallback();
 1577            iceI_ice_flushBatchRequests(completed, true);
 1578            completed.Task.Wait();
 1579        }
 1580        catch (AggregateException ex)
 1581        {
 1582            throw ex.InnerException!;
 1583        }
 1584    }
 1585
 1586    internal const string _ice_flushBatchRequests_name = "ice_flushBatchRequests";
 1587
 1588    public Task ice_flushBatchRequestsAsync(
 1589        IProgress<bool>? progress = null,
 1590        CancellationToken cancel = default)
 1591    {
 1592        var completed = new FlushBatchTaskCompletionCallback(progress, cancel);
 1593        iceI_ice_flushBatchRequests(completed, false);
 1594        return completed.Task;
 1595    }
 1596
 1597    private void iceI_ice_flushBatchRequests(OutgoingAsyncCompletionCallback completed, bool synchronous)
 1598    {
 1599        var outgoing = new ProxyFlushBatchAsync(this, completed);
 1600        outgoing.invoke(_ice_flushBatchRequests_name, synchronous);
 1601    }
 1602
 1603    public System.Threading.Tasks.TaskScheduler ice_scheduler() => _reference.getThreadPool();
 1604
 1605    [EditorBrowsable(EditorBrowsableState.Never)]
 1606    public void iceWrite(OutputStream os)
 1607    {
 1608        Identity.ice_write(os, _reference.getIdentity());
 1609        _reference.streamWrite(os);
 1610    }
 1611
 1612    internal Reference iceReference() => _reference;
 1613
 1614    [EditorBrowsable(EditorBrowsableState.Never)]
 1615    public void iceCheckTwowayOnly(string name)
 1616    {
 1617        //
 1618        // No mutex lock necessary, there is nothing mutable in this
 1619        // operation.
 1620        //
 1621
 1622        if (!ice_isTwoway())
 1623        {
 1624            throw new TwowayOnlyException(name);
 1625        }
 1626    }
 1627
 1628    internal RequestHandlerCache iceGetRequestHandlerCache() => _requestHandlerCache;
 1629
 1630    protected ObjectPrxHelperBase(ObjectPrx proxy)
 1631    {
 1632        // We don't supported decorated proxies here.
 1633        var helper = (ObjectPrxHelperBase)proxy;
 1634
 1635        _reference = helper._reference;
 1636        _requestHandlerCache = helper._requestHandlerCache;
 1637    }
 1638
 1639    protected OutgoingAsyncT<T>
 1640    getOutgoingAsync<T>(OutgoingAsyncCompletionCallback completed)
 1641    {
 1642        bool haveEntry = false;
 1643        InputStream? iss = null;
 1644        OutputStream? os = null;
 1645
 1646        if (_reference.getInstance().cacheMessageBuffers() > 0)
 1647        {
 1648            lock (_mutex)
 1649            {
 1650                if (_streamCache != null && _streamCache.Count > 0)
 1651                {
 1652                    haveEntry = true;
 1653                    iss = _streamCache.First!.Value.iss;
 1654                    os = _streamCache.First.Value.os;
 1655
 1656                    _streamCache.RemoveFirst();
 1657                }
 1658            }
 1659        }
 1660        if (!haveEntry)
 1661        {
 1662            return new OutgoingAsyncT<T>(this, completed);
 1663        }
 1664        else
 1665        {
 1666            return new OutgoingAsyncT<T>(this, completed, os, iss);
 1667        }
 1668    }
 1669
 1670    private class InvokeOutgoingAsyncT : OutgoingAsync
 1671    {
 1672        public InvokeOutgoingAsyncT(
 1673            ObjectPrxHelperBase prx,
 1674            OutgoingAsyncCompletionCallback completionCallback,
 1675            OutputStream? os = null,
 1676            InputStream? iss = null)
 1677            : base(prx, completionCallback, os, iss)
 1678        {
 1679        }
 1680
 1681        public void invoke(
 1682            string operation,
 1683            OperationMode mode,
 1684            byte[] inParams,
 1685            Dictionary<string, string>? context,
 1686            bool synchronous)
 1687        {
 1688            try
 1689            {
 1690                prepare(operation, mode, context);
 1691                if (inParams is null || inParams.Length == 0)
 1692                {
 1693                    os_.writeEmptyEncapsulation(encoding_);
 1694                }
 1695                else
 1696                {
 1697                    os_.writeEncapsulation(inParams);
 1698                }
 1699                invoke(operation, synchronous);
 1700            }
 1701            catch (Exception ex)
 1702            {
 1703                abort(ex);
 1704            }
 1705        }
 1706
 1707        public Object_Ice_invokeResult
 1708        getResult(bool ok)
 1709        {
 1710            try
 1711            {
 1712                var ret = new Object_Ice_invokeResult();
 1713                if (proxy_.iceReference().isTwoway)
 1714                {
 1715                    ret.outEncaps = is_.readEncapsulation(out _);
 1716                }
 1717                else
 1718                {
 1719                    ret.outEncaps = [];
 1720                }
 1721                ret.returnValue = ok;
 1722                return ret;
 1723            }
 1724            finally
 1725            {
 1726                cacheMessageBuffers();
 1727            }
 1728        }
 1729    }
 1730
 1731    private class InvokeTaskCompletionCallback : TaskCompletionCallback<Object_Ice_invokeResult>
 1732    {
 1733        public InvokeTaskCompletionCallback(IProgress<bool>? progress, CancellationToken cancellationToken)
 1734            : base(progress, cancellationToken)
 1735        {
 1736        }
 1737
 1738        public override void handleInvokeSent(
 1739            bool sentSynchronously,
 1740            bool done,
 1741            bool alreadySent,
 1742            OutgoingAsyncBase og)
 1743        {
 1744            if (progress_ != null && !alreadySent)
 1745            {
 1746                progress_.Report(sentSynchronously);
 1747            }
 1748            if (done)
 1749            {
 1750                SetResult(new Object_Ice_invokeResult(true, []));
 1751            }
 1752        }
 1753
 1754        public override void handleInvokeResponse(bool ok, OutgoingAsyncBase og) =>
 1755            SetResult(((InvokeOutgoingAsyncT)og).getResult(ok));
 1756    }
 1757
 1758    private InvokeOutgoingAsyncT
 1759    getInvokeOutgoingAsync(OutgoingAsyncCompletionCallback completed)
 1760    {
 1761        bool haveEntry = false;
 1762        InputStream? iss = null;
 1763        OutputStream? os = null;
 1764
 1765        if (_reference.getInstance().cacheMessageBuffers() > 0)
 1766        {
 1767            lock (_mutex)
 1768            {
 1769                if (_streamCache != null && _streamCache.Count > 0)
 1770                {
 1771                    haveEntry = true;
 1772                    iss = _streamCache.First!.Value.iss;
 1773                    os = _streamCache.First.Value.os;
 1774
 1775                    _streamCache.RemoveFirst();
 1776                }
 1777            }
 1778        }
 1779        if (!haveEntry)
 1780        {
 1781            return new InvokeOutgoingAsyncT(this, completed);
 1782        }
 1783        else
 1784        {
 1785            return new InvokeOutgoingAsyncT(this, completed, os, iss);
 1786        }
 1787    }
 1788
 1789    internal void cacheMessageBuffers(InputStream iss, OutputStream os)
 1790    {
 1791        lock (_mutex)
 1792        {
 1793            _streamCache ??= new LinkedList<(InputStream, OutputStream)>();
 1794            _streamCache.AddLast((iss, os));
 1795        }
 1796    }
 1797
 1798    /// <summary>
 1799    /// Initializes a new instance of the <see cref="ObjectPrxHelperBase" /> class.
 1800    /// </summary>
 1801    /// <param name="reference">The reference for the new proxy.</param>
 1802    [EditorBrowsable(EditorBrowsableState.Never)]
 1803    protected ObjectPrxHelperBase(Reference reference)
 1804    {
 1805        _reference = reference;
 1806        _requestHandlerCache = new RequestHandlerCache(reference);
 1807    }
 1808
 1809    /// <summary>
 1810    /// Constructs a new proxy instance.
 1811    /// </summary>
 1812    /// <param name="reference">The reference for the new proxy.</param>
 1813    /// <returns>The new proxy instance.</returns>
 1814    [EditorBrowsable(EditorBrowsableState.Never)]
 1815    protected abstract ObjectPrxHelperBase iceNewInstance(Reference reference);
 1816
 1817    // Rounds a nonnegative timeout of at most int.MaxValue units up to a whole number of the given unit.
 1818    private static TimeSpan roundUp(TimeSpan timeout, long ticksPerUnit)
 1819    {
 1820        long remainder = timeout.Ticks % ticksPerUnit;
 1821        if (remainder == 0)
 1822        {
 1823            return timeout;
 1824        }
 1825        return TimeSpan.FromTicks(timeout.Ticks - remainder + ticksPerUnit);
 1826    }
 1827
 1828    private readonly Reference _reference;
 1829    private readonly RequestHandlerCache _requestHandlerCache;
 1830    private LinkedList<(InputStream iss, OutputStream os)>? _streamCache;
 1831    private readonly object _mutex = new();
 1832}
 1833
 1834/// <summary>
 1835/// The concrete proxy class that implements <see cref="ObjectPrx" />.
 1836/// </summary>
 1837public class ObjectPrxHelper : ObjectPrxHelperBase
 1838{
 1839    /// <summary>
 1840    /// Creates a new proxy that implements <see cref="ObjectPrx" />.
 1841    /// </summary>
 1842    /// <param name="communicator">The communicator of the new proxy.</param>
 1843    /// <param name="proxyString">The string representation of the proxy.</param>
 1844    /// <returns>The new proxy.</returns>
 1845    /// <exception cref="ParseException">Thrown when <paramref name="proxyString" /> is not a valid proxy string.
 1846    /// </exception>
 1847    public static ObjectPrx createProxy(Communicator communicator, string proxyString)
 1848    {
 1849        Reference? reference = communicator.instance.referenceFactory().create(proxyString, "");
 1850
 1851        return reference is not null ?
 1852            new ObjectPrxHelper(reference) :
 1853            throw new ParseException("Invalid empty proxy string.");
 1854    }
 1855
 1856    /// <summary>
 1857    /// Creates a new proxy from an existing proxy after confirming the target object's type via a remote invocation.
 1858    /// </summary>
 1859    /// <param name="proxy">The source proxy.</param>
 1860    /// <param name="context">The request context.</param>
 1861    /// <returns>A new proxy with the requested type, or null if the target object does not support the requested type.
 1862    /// </returns>
 1863    public static ObjectPrx? checkedCast(ObjectPrx? proxy, Dictionary<string, string>? context = null) =>
 1864        proxy is not null && proxy.ice_isA("::Ice::Object", context) ? proxy : null;
 1865
 1866    /// <summary>
 1867    /// Creates a new proxy from an existing proxy after confirming the target object's type via a remote invocation.
 1868    /// </summary>
 1869    /// <param name="proxy">The source proxy (can be null).</param>
 1870    /// <param name="facet">A facet name.</param>
 1871    /// <param name="context">The request context.</param>
 1872    /// <returns>A new proxy with the requested type and facet, or null if the target facet does not support the
 1873    /// requested type.</returns>
 1874    public static ObjectPrx? checkedCast(ObjectPrx? proxy, string facet, Dictionary<string, string>? context = null) =>
 1875        checkedCast(proxy?.ice_facet(facet), context);
 1876
 1877    /// <summary>
 1878    /// Creates a new proxy from an existing proxy after confirming the target object's type via a remote invocation.
 1879    /// </summary>
 1880    /// <param name="proxy">The source proxy.</param>
 1881    /// <param name="context">The request context.</param>
 1882    /// <param name="progress">Sent progress provider.</param>
 1883    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 1884    /// <returns>A new proxy with the requested type, or null if the target object does not support the requested type.
 1885    /// </returns>
 1886    public static async Task<ObjectPrx?> checkedCastAsync(
 1887        ObjectPrx proxy,
 1888        Dictionary<string, string>? context = null,
 1889        IProgress<bool>? progress = null,
 1890        CancellationToken cancel = default) =>
 1891       await proxy.ice_isAAsync("::Ice::Object", context, progress, cancel).ConfigureAwait(false) ? proxy : null;
 1892
 1893    /// <summary>
 1894    /// Creates a new proxy from an existing proxy after confirming the target object's type via a remote invocation.
 1895    /// </summary>
 1896    /// <param name="proxy">The source proxy.</param>
 1897    /// <param name="facet">A facet name.</param>
 1898    /// <param name="context">The request context.</param>
 1899    /// <param name="progress">Sent progress provider.</param>
 1900    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 1901    /// <returns>A new proxy with the requested type and facet, or null if the target facet does not support the
 1902    /// requested type.</returns>
 1903    public static Task<ObjectPrx?> checkedCastAsync(
 1904        ObjectPrx proxy,
 1905        string facet,
 1906        Dictionary<string, string>? context = null,
 1907        IProgress<bool>? progress = null,
 1908        CancellationToken cancel = default) =>
 1909        checkedCastAsync(proxy.ice_facet(facet), context, progress, cancel);
 1910
 1911    /// <summary>
 1912    /// Creates a new proxy from an existing proxy.
 1913    /// </summary>
 1914    /// <param name="proxy">The source proxy.</param>
 1915    /// <returns>A new proxy with the requested type.</returns>
 1916    /// <remarks>This is a purely local operation.</remarks>
 1917    [return: NotNullIfNotNull(nameof(proxy))]
 1918    public static ObjectPrx? uncheckedCast(ObjectPrx? proxy) => proxy;
 1919
 1920    /// <summary>
 1921    /// Creates a new proxy from an existing proxy.
 1922    /// </summary>
 1923    /// <param name="proxy">The source proxy.</param>
 1924    /// <param name="facet">A facet name.</param>
 1925    /// <returns>A new proxy with the requested type and facet, or null if the source proxy is null.</returns>
 1926    /// <remarks>This is a purely local operation.</remarks>
 1927    [return: NotNullIfNotNull(nameof(proxy))]
 1928    public static ObjectPrx? uncheckedCast(ObjectPrx? proxy, string facet) => proxy?.ice_facet(facet);
 1929
 1930    /// <summary>
 1931    /// Gets the Slice type id of the interface or class associated with this proxy class.
 1932    /// </summary>
 1933    /// <returns>The type id, "::Ice::Object".</returns>
 1934    public static string ice_staticId() => Object.ice_staticId();
 1935
 1936    protected override ObjectPrxHelperBase iceNewInstance(Reference reference) => new ObjectPrxHelper(reference);
 1937
 1938    internal ObjectPrxHelper(Reference reference)
 1939        : base(reference)
 1940    {
 1941    }
 1942}