< Summary

Information
Class: Ice.Communicator
Assembly: Ice
File(s): /_/csharp/src/Ice/Communicator.cs
Tag: 125_37167941578
Line coverage
92%
Covered lines: 84
Uncovered lines: 7
Coverable lines: 91
Total lines: 524
Line coverage: 92.3%
Branch coverage
85%
Covered branches: 12
Total branches: 14
Branch coverage: 85.7%
Method coverage
91%
Covered methods: 34
Fully covered methods: 32
Total methods: 37
Method coverage: 91.8%
Full method coverage: 86.4%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_shutdownCompleted()100%11100%
.ctor(...)100%22100%
.ctor(...)100%210%
Dispose()100%11100%
DisposeAsync()100%11100%
destroy()100%11100%
shutdown()100%11100%
waitForShutdown()100%11100%
isShutdown()100%11100%
stringToProxy(...)100%22100%
proxyToString(...)50%22100%
propertyToProxy(...)100%22100%
proxyToProperty(...)100%11100%
identityToString(...)100%11100%
createObjectAdapter(...)100%11100%
createObjectAdapterWithEndpoints(...)50%2275%
createObjectAdapterWithRouter(...)100%44100%
getDefaultObjectAdapter()100%11100%
setDefaultObjectAdapter(...)100%11100%
getImplicitContext()100%11100%
getProperties()100%11100%
getLogger()100%11100%
addSliceLoader(...)100%210%
getObserver()100%210%
getDefaultRouter()100%11100%
setDefaultRouter(...)100%11100%
getDefaultLocator()100%11100%
setDefaultLocator(...)100%11100%
getPluginManager()100%11100%
flushBatchRequests(...)100%1175%
flushBatchRequestsAsync(...)100%11100%
createAdmin(...)100%11100%
getAdmin()100%11100%
addAdminFacet(...)100%11100%
removeAdminFacet(...)100%11100%
findAdminFacet(...)100%11100%
findAllAdminFacets()100%11100%

File(s)

/_/csharp/src/Ice/Communicator.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using Ice.Internal;
 6using System.Net.Security;
 7
 8namespace Ice;
 9
 10/// <summary>
 11/// Communicator is the central object in Ice. Its responsibilities include:
 12/// <list type="bullet">
 13/// <item>creating and managing outgoing connections</item>
 14/// <item>executing callbacks in its client thread pool</item>
 15/// <item>creating and destroying object adapters</item>
 16/// <item>loading plug-ins</item>
 17/// <item>managing properties (configuration), retries, logging, instrumentation, and more.</item>
 18/// </list>
 19/// A Communicator is usually the first object you create when programming with Ice.
 20/// You can create multiple communicators in a single program, but this is not common.
 21/// </summary>
 22/// <seealso cref="Logger"/>
 23/// <seealso cref="ObjectAdapter"/>
 24/// <seealso cref="Properties"/>
 25public sealed class Communicator : IDisposable, IAsyncDisposable
 26{
 27    /// <summary>
 28    /// Gets a task that completes when the communicator's shutdown completes. This task always completes successfully.
 29    /// </summary>
 30    /// <remarks>The shutdown of a communicator completes when all its incoming connections are closed. Awaiting this
 31    /// task is equivalent to calling <see cref="waitForShutdown" />.</remarks>
 32    /// <seealso cref="shutdown" />
 33    public Task shutdownCompleted
 34    {
 35        get
 36        {
 37            // It would be much nicer to wait asynchronously but doing so requires significant refactoring.
 138            var tcs = new TaskCompletionSource(); // created "on demand", when the user calls shutdownCompleted
 139            _ = Task.Run(() =>
 140            {
 141                waitForShutdown();
 142                tcs.SetResult();
 143            });
 144            return tcs.Task;
 45        }
 46    }
 47
 48    internal Instance instance { get; }
 49
 50    private const string _flushBatchRequests_name = "flushBatchRequests";
 51
 52    /// <summary>
 53    /// Initializes a new instance of the <see cref="Communicator" /> class.
 54    /// </summary>
 55    /// <param name="initData">Options for the new communicator.</param>
 156    public Communicator(InitializationData? initData = null)
 57    {
 158        initData = initData is null ? new InitializationData() : initData with { };
 59
 160        instance = new Instance();
 161        instance.initialize(this, initData);
 62
 63        try
 64        {
 165            instance.finishSetup(this);
 166        }
 167        catch
 68        {
 169            instance.destroy();
 170            throw;
 71        }
 172    }
 73
 74    /// <summary>
 75    /// Initializes a new instance of the <see cref="Communicator" /> class, using Ice properties parsed from
 76    /// command-line arguments. This constructor uses <paramref name="args"/> to create the <see cref="Properties"/>
 77    /// of the new communicator.
 78    /// </summary>
 79    /// <param name="args">The command-line arguments.</param>
 80    public Communicator(ref string[] args)
 081        : this(new InitializationData { properties = new Properties(ref args) })
 82    {
 083    }
 84
 85    /// <summary>
 86    /// Disposes this communicator. This method calls <see cref="shutdown" /> implicitly. Calling dispose destroys all
 87    /// object adapters, and closes all outgoing connections. This method waits for all outstanding dispatches to
 88    /// complete before returning. This includes "bidirectional dispatches" that execute on outgoing connections.
 89    /// </summary>
 190    public void Dispose() => destroy();
 91
 92    /// <summary>
 93    /// Disposes this communicator asynchronously. Like <see cref="Communicator.shutdownCompleted" />, this method
 94    /// waits for all outstanding dispatches to complete.
 95    /// </summary>
 96    /// <returns>A task that completes when the communicator is disposed.</returns>
 97    public ValueTask DisposeAsync()
 98    {
 99        // A truly async implementation would be nicer but requires significant refactoring.
 1100        var tcs = new TaskCompletionSource();
 1101        _ = Task.Run(() =>
 1102        {
 1103            Dispose(); // can block for a while
 1104            tcs.SetResult();
 1105        });
 106
 1107        return new(tcs.Task);
 108    }
 109
 110    /// <summary>
 111    /// Destroys this communicator. It's an alias for <see cref="Dispose"/>.
 112    /// </summary>
 1113    public void destroy() => instance.destroy();
 114
 115    /// <summary>
 116    /// Shuts down this communicator. This method calls <see cref="ObjectAdapter.deactivate"/> on all object adapters
 117    /// created by this communicator. Shutting down a communicator has no effect on outgoing connections.
 118    /// </summary>
 119    /// <seealso cref="waitForShutdown" />
 120    public void shutdown()
 121    {
 122        try
 123        {
 1124            instance.objectAdapterFactory().shutdown();
 1125        }
 1126        catch (CommunicatorDestroyedException)
 127        {
 128            // Ignore
 1129        }
 1130    }
 131
 132    /// <summary>
 133    /// Waits for the shutdown of this communicator to complete.
 134    /// This method calls <see cref="ObjectAdapter.waitForDeactivate" /> on all object adapters created by this
 135    /// communicator. In a client application that does not accept incoming connections, this method returns as soon as
 136    /// another thread calls <see cref="shutdown" /> or <see cref="Dispose" /> on this communicator.
 137    /// </summary>
 138    public void waitForShutdown()
 139    {
 140        try
 141        {
 1142            instance.objectAdapterFactory().waitForShutdown();
 1143        }
 1144        catch (CommunicatorDestroyedException)
 145        {
 146            // Ignore
 1147        }
 1148    }
 149
 150    /// <summary>
 151    /// Checks whether or not <see cref="shutdown" /> was called on this communicator.
 152    /// </summary>
 153    /// <returns><see langword="true"/> if shutdown was called on this communicator; otherwise,
 154    /// <see langword="false"/>.</returns>
 155    public bool isShutdown()
 156    {
 157        try
 158        {
 1159            return instance.objectAdapterFactory().isShutdown();
 160        }
 1161        catch (CommunicatorDestroyedException)
 162        {
 1163            return true;
 164        }
 1165    }
 166
 167    /// <summary>
 168    /// Converts a stringified proxy into a proxy.
 169    /// </summary>
 170    /// <param name="str">The stringified proxy to convert into a proxy.</param>
 171    /// <returns>The proxy, or null if <paramref name="str" /> is an empty string.</returns>
 172    /// <exception cref="ParseException">Thrown when <paramref name="str" /> is not a valid proxy string.</exception>
 173    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 174    public ObjectPrx? stringToProxy(string str)
 175    {
 1176        Reference? reference = instance.referenceFactory().create(str, "");
 1177        return reference is not null ? new ObjectPrxHelper(reference) : null;
 178    }
 179
 180    /// <summary>
 181    /// Converts a proxy into a string.
 182    /// </summary>
 183    /// <param name="proxy">The proxy to convert into a stringified proxy.</param>
 184    /// <returns>The stringified proxy, or an empty string if <paramref name="proxy" /> is null.</returns>
 185    public string proxyToString(ObjectPrx? proxy) =>
 1186        proxy is null ? "" : ((ObjectPrxHelperBase)proxy).iceReference().ToString();
 187
 188    /// <summary>
 189    /// Converts a set of proxy properties into a proxy. The "base" name supplied in the <paramref name="property" />
 190    /// argument refers to a property containing a stringified proxy, such as `MyProxy=id:tcp -h localhost -p 10000`.
 191    /// Additional properties configure local settings for the proxy.
 192    /// </summary>
 193    /// <param name="property">The base property name.</param>
 194    /// <returns>The proxy, or <c>null</c> if the property is not set.</returns>
 195    /// <exception cref="ParseException">Thrown when the property value is not a valid proxy string.</exception>
 196    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 197    public ObjectPrx? propertyToProxy(string property)
 198    {
 1199        string proxy = instance.initializationData().properties!.getProperty(property);
 1200        Reference? reference = instance.referenceFactory().create(proxy, property);
 1201        return reference is not null ? new ObjectPrxHelper(reference) : null;
 202    }
 203
 204    /// <summary>
 205    /// Converts a proxy into a set of proxy properties.
 206    /// </summary>
 207    /// <param name="proxy">The proxy.</param>
 208    /// <param name="prefix">The base property name.</param>
 209    /// <returns>The property set.</returns>
 210    public Dictionary<string, string> proxyToProperty(ObjectPrx proxy, string prefix) =>
 1211        ((ObjectPrxHelperBase)proxy).iceReference().toProperty(prefix);
 212
 213    /// <summary>
 214    /// Converts an identity into a string.
 215    /// </summary>
 216    /// <param name="ident">The identity to convert into a string.</param>
 217    /// <returns>The "stringified" identity.</returns>
 1218    public string identityToString(Identity ident) => Util.identityToString(ident, instance.toStringMode());
 219
 220    /// <summary>
 221    /// Creates a new object adapter. The endpoints for the object adapter are taken from the property
 222    /// <c>name.Endpoints</c>.
 223    /// It is legal to create an object adapter with the empty string as its name. Such an object
 224    /// adapter is accessible via bidirectional connections or by collocated invocations.
 225    /// </summary>
 226    /// <param name="name">The object adapter name.</param>
 227    /// <param name="serverAuthenticationOptions">The SSL options for server connections.</param>
 228    /// <returns>The new object adapter.</returns>
 229    /// <exception cref="InitializationException">Thrown when a named object adapter is created for which no
 230    /// configuration can be found.</exception>
 231    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 232    public ObjectAdapter createObjectAdapter(
 233        string name,
 234        SslServerAuthenticationOptions? serverAuthenticationOptions = null) =>
 1235        instance.objectAdapterFactory().createObjectAdapter(name, null, serverAuthenticationOptions);
 236
 237    /// <summary>
 238    /// Creates a new object adapter with endpoints. This method sets the property <c>name.Endpoints</c>,
 239    /// and then calls <see cref="createObjectAdapter"/>. It is provided as a convenience method.
 240    /// Calling this method with an empty name will result in a UUID being generated for the name.
 241    /// </summary>
 242    /// <param name="name">The object adapter name.</param>
 243    /// <param name="endpoints">The endpoints of the object adapter.</param>
 244    /// <param name="serverAuthenticationOptions">The SSL options for server connections.</param>
 245    /// <returns>The new object adapter.</returns>
 246    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 247    public ObjectAdapter createObjectAdapterWithEndpoints(
 248        string name,
 249        string endpoints,
 250        SslServerAuthenticationOptions? serverAuthenticationOptions = null)
 251    {
 1252        if (name.Length == 0)
 253        {
 0254            name = Guid.NewGuid().ToString();
 255        }
 256
 1257        getProperties().setProperty(name + ".Endpoints", endpoints);
 1258        return instance.objectAdapterFactory().createObjectAdapter(name, null, serverAuthenticationOptions);
 259    }
 260
 261    /// <summary>
 262    /// Creates a new object adapter with a router.
 263    /// This method creates a routed object adapter. Calling this method with an empty name will result in a UUID
 264    /// being generated for the name.
 265    /// </summary>
 266    /// <param name="name">The object adapter name.</param>
 267    /// <param name="router">The router.</param>
 268    /// <returns>The new object adapter.</returns>
 269    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 270    public ObjectAdapter createObjectAdapterWithRouter(string name, RouterPrx router)
 271    {
 1272        if (name.Length == 0)
 273        {
 1274            name = Guid.NewGuid().ToString();
 275        }
 276
 277        //
 278        // We set the proxy properties here, although we still use the proxy supplied.
 279        //
 1280        Dictionary<string, string> properties = proxyToProperty(router, name + ".Router");
 1281        foreach (KeyValuePair<string, string> entry in properties)
 282        {
 1283            getProperties().setProperty(entry.Key, entry.Value);
 284        }
 285
 1286        return instance.objectAdapterFactory().createObjectAdapter(name, router, serverAuthenticationOptions: null);
 287    }
 288
 289    /// <summary>
 290    /// Gets the object adapter that is associated by default with new outgoing connections created by this
 291    /// communicator. This method returns null unless you set a non-null default object adapter using
 292    /// <see cref="setDefaultObjectAdapter" />.
 293    /// </summary>
 294    /// <returns>The object adapter associated by default with new outgoing connections.</returns>
 295    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 296    /// <seealso cref="Connection.getAdapter" />
 1297    public ObjectAdapter? getDefaultObjectAdapter() => instance.outgoingConnectionFactory().getDefaultObjectAdapter();
 298
 299    /// <summary>
 300    /// Sets the object adapter that will be associated with new outgoing connections created by this communicator. This
 301    /// method has no effect on existing outgoing connections, or on incoming connections.
 302    /// </summary>
 303    /// <param name="adapter">The object adapter to associate with new outgoing connections.</param>
 304    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 305    /// <seealso cref="Connection.setAdapter" />
 306    public void setDefaultObjectAdapter(ObjectAdapter? adapter) =>
 1307        instance.outgoingConnectionFactory().setDefaultObjectAdapter(adapter);
 308
 309    /// <summary>
 310    /// Gets the implicit context associated with this communicator.
 311    /// </summary>
 312    /// <returns>The implicit context associated with this communicator; returns null when the property
 313    /// Ice.ImplicitContext is not set or is set to None.</returns>
 1314    public ImplicitContext getImplicitContext() => instance.getImplicitContext();
 315
 316    /// <summary>
 317    /// Gets the properties for this communicator.
 318    /// </summary>
 319    /// <returns>This communicator's properties.</returns>
 1320    public Properties getProperties() => instance.initializationData().properties!;
 321
 322    /// <summary>
 323    /// Gets the logger for this communicator.
 324    /// </summary>
 325    /// <returns>This communicator's logger.</returns>
 1326    public Logger getLogger() => instance.initializationData().logger!;
 327
 328    /// <summary>
 329    /// Adds a Slice loader to this communicator, after the Slice loader set in <see cref="InitializationData" />(if
 330    /// any) and after other Slice loaders added by this method.
 331    /// </summary>
 332    /// <param name="loader"> The Slice loader to add.</param>
 333    /// <remarks>This method is not thread-safe and should only be called right after the communicator is created.
 334    /// It's provided for applications that cannot set the Slice loader in the <see cref="InitializationData" /> of the
 335    /// communicator, such as IceBox services.</remarks>
 0336    public void addSliceLoader(SliceLoader loader) => instance.addSliceLoader(loader);
 337
 338    /// <summary>
 339    /// Gets the observer resolver object for this communicator.
 340    /// </summary>
 341    /// <returns>This communicator's observer resolver object.</returns>
 0342    public Instrumentation.CommunicatorObserver? getObserver() => instance.initializationData().observer;
 343
 344    /// <summary>
 345    /// Gets the default router for this communicator.
 346    /// </summary>
 347    /// <returns>The default router for this communicator.</returns>
 348    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1349    public RouterPrx? getDefaultRouter() => instance.referenceFactory().getDefaultRouter();
 350
 351    /// <summary>
 352    /// Sets a default router for this communicator.
 353    /// All newly created proxies will use this default router. To disable the default router, null can be used. Note
 354    /// that this method has no effect on existing proxies. You can also set a router for an individual proxy by calling
 355    /// <see cref="ObjectPrx.ice_router(RouterPrx?)" /> on the proxy.
 356    /// </summary>
 357    /// <param name="router">The default router to use for this communicator.</param>
 358    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1359    public void setDefaultRouter(RouterPrx? router) => instance.setDefaultRouter(router);
 360
 361    /// <summary>
 362    /// Gets the default locator for this communicator.
 363    /// </summary>
 364    /// <returns>The default locator for this communicator.</returns>
 365    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1366    public LocatorPrx? getDefaultLocator() => instance.referenceFactory().getDefaultLocator();
 367
 368    /// <summary>
 369    /// Sets a default Ice locator for this communicator.
 370    /// All newly created proxy and object adapters will use this default locator. To disable the default locator, null
 371    /// can be used. Note that this method has no effect on existing proxies or object adapters.
 372    /// You can also set a locator for an individual proxy by calling <see cref="ObjectPrx.ice_locator(LocatorPrx?)" />
 373    /// on the proxy, or for an object adapter by calling <see cref="ObjectAdapter.setLocator(LocatorPrx)" /> on the
 374    /// object adapter.
 375    /// </summary>
 376    /// <param name="locator">The default locator to use for this communicator.</param>
 377    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1378    public void setDefaultLocator(LocatorPrx? locator) => instance.setDefaultLocator(locator);
 379
 380    /// <summary>
 381    /// Gets the plug-in manager for this communicator.
 382    /// </summary>
 383    /// <returns>This communicator's plug-in manager.</returns>
 384    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1385    public PluginManager getPluginManager() => instance.pluginManager();
 386
 387    /// <summary>
 388    /// Flushes any pending batch requests for this communicator.
 389    /// This means all batch requests invoked on fixed proxies for all connections associated with the communicator.
 390    /// Any errors that occur while flushing a connection are ignored.
 391    /// </summary>
 392    /// <param name="compress">Specifies whether or not the queued batch requests should be compressed before being sent
 393    /// over the wire.</param>
 394    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 395    public void flushBatchRequests(CompressBatch compress)
 396    {
 397        try
 398        {
 1399            var completed = new FlushBatchTaskCompletionCallback();
 1400            var outgoing = new CommunicatorFlushBatchAsync(instance, completed);
 1401            outgoing.invoke(_flushBatchRequests_name, compress, true);
 1402            completed.Task.Wait();
 1403        }
 0404        catch (AggregateException ex)
 405        {
 0406            throw ex.InnerException!;
 407        }
 1408    }
 409
 410    /// <summary>
 411    /// Flushes any pending batch requests for this communicator.
 412    /// This means all batch requests invoked on fixed proxies for all connections associated with the communicator.
 413    /// Any errors that occur while flushing a connection are ignored.
 414    /// </summary>
 415    /// <param name="compress">Specifies whether or not the queued batch requests should be compressed before being sent
 416    /// over the wire.</param>
 417    /// <param name="progress">The sent progress provider.</param>
 418    /// <param name="cancel">A cancellation token that receives the cancellation requests.</param>
 419    /// <returns>A task that completes when the flush completes for all connections.</returns>
 420    /// <exception cref="CommunicatorDestroyedException">Thrown synchronously when the communicator has been
 421    /// destroyed.</exception>
 422    public Task flushBatchRequestsAsync(
 423        CompressBatch compress,
 424        IProgress<bool>? progress = null,
 425        CancellationToken cancel = default)
 426    {
 1427        var completed = new FlushBatchTaskCompletionCallback(progress, cancel);
 1428        var outgoing = new CommunicatorFlushBatchAsync(instance, completed);
 1429        outgoing.invoke(_flushBatchRequests_name, compress, false);
 1430        return completed.Task;
 431    }
 432
 433    /// <summary>
 434    /// Adds the Admin object with all its facets to the provided object adapter.
 435    /// If Ice.Admin.ServerId is set and the provided object adapter has a Locator, createAdmin registers the Admin's
 436    /// Process facet with the Locator's LocatorRegistry. createAdmin must only be called once; subsequent calls raise
 437    /// InitializationException.
 438    /// </summary>
 439    /// <param name="adminAdapter">The object adapter used to host the Admin object; if null and Ice.Admin.Endpoints is
 440    /// set, create, activate and use the Ice.Admin object adapter.</param>
 441    /// <param name="adminId">The identity of the Admin object.</param>
 442    /// <returns>A proxy to the main ("") facet of the Admin object.</returns>
 443    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 444    public ObjectPrx createAdmin(ObjectAdapter adminAdapter, Identity adminId) =>
 1445        instance.createAdmin(adminAdapter, adminId);
 446
 447    /// <summary>
 448    /// Gets a proxy to the main facet of the Admin object.
 449    /// getAdmin also creates the Admin object and creates and activates the Ice.Admin object adapter to host this
 450    /// Admin object if Ice.Admin.Endpoints is set. The identity of the Admin object created by getAdmin is
 451    /// {value of Ice.Admin.InstanceName}/admin, or {UUID}/admin when  Ice.Admin.InstanceName is not set. If
 452    /// Ice.Admin.DelayCreation is 0 or not set, getAdmin is called  by the communicator initialization, after
 453    /// initialization of all plugins.
 454    /// </summary>
 455    /// <returns>A proxy to the main ("") facet of the Admin object, or a null proxy if no Admin object is configured.
 456    /// </returns>
 457    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1458    public ObjectPrx? getAdmin() => instance.getAdmin();
 459
 460    /// <summary>
 461    /// Adds a new facet to the Admin object.
 462    /// Adding a servant with a facet that is already registered throws AlreadyRegisteredException.
 463    /// </summary>
 464    /// <param name="servant">The servant that implements the new Admin facet.</param>
 465    /// <param name="facet">The name of the new Admin facet.</param>
 466    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1467    public void addAdminFacet(Object servant, string facet) => instance.addAdminFacet(servant, facet);
 468
 469    /// <summary>
 470    /// Removes a facet from the Admin object.
 471    /// Removing a facet that was not previously registered throws <see cref="NotRegisteredException" />.
 472    /// </summary>
 473    /// <param name="facet">The name of the Admin facet.</param>
 474    /// <returns>The servant associated with this Admin facet.</returns>
 475    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1476    public Object removeAdminFacet(string facet) => instance.removeAdminFacet(facet);
 477
 478    /// <summary>
 479    /// Returns a facet of the Admin object.
 480    /// </summary>
 481    /// <param name="facet">The name of the Admin facet.</param>
 482    /// <returns>The servant associated with this Admin facet, or null if no facet is registered with the given name.
 483    /// </returns>
 484    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1485    public Object? findAdminFacet(string facet) => instance.findAdminFacet(facet);
 486
 487    /// <summary>
 488    /// Returns a map of all facets of the Admin object.
 489    /// </summary>
 490    /// <returns>A collection containing all the facet names and servants of the Admin object.</returns>
 491    /// <exception cref="CommunicatorDestroyedException">Thrown when the communicator has been destroyed.</exception>
 1492    public Dictionary<string, Object> findAllAdminFacets() => instance.findAllAdminFacets();
 493}
 494
 495/// <summary>
 496/// The output mode for xxxToString methods such as identityToString and proxyToString.
 497/// The actual encoding format for
 498/// the string is the same for all modes: you don't need to specify an encoding format or mode when reading such a
 499/// string.
 500/// </summary>
 501public enum ToStringMode
 502{
 503    /// <summary>
 504    /// Characters with ordinal values greater than 127 are kept as-is in the resulting string.
 505    /// Non-printable ASCII
 506    /// characters with ordinal values 127 and below are encoded as \t, \n (etc.) or \unnnn.
 507    /// </summary>
 508    Unicode,
 509
 510    /// <summary>
 511    /// Characters with ordinal values greater than 127 are encoded as universal character names in the resulting
 512    /// string: \unnnn for BMP characters and \Unnnnnnnn for non-BMP characters.
 513    /// Non-printable ASCII characters
 514    /// with ordinal values 127 and below are encoded as \t, \n (etc.) or \unnnn.
 515    /// </summary>
 516    ASCII,
 517
 518    /// <summary>
 519    /// Characters with ordinal values greater than 127 are encoded as a sequence of UTF-8 bytes using octal escapes.
 520    /// Non-printable ASCII characters with ordinal values 127 and below are encoded as \t, \n (etc.) or an octal
 521    /// escape. Use this mode to generate strings compatible with Ice 3.6 and earlier.
 522    /// </summary>
 523    Compat
 524}