| | 1 | | // Copyright (c) ZeroC, Inc. |
| | 2 | |
|
| | 3 | | #nullable enable |
| | 4 | |
|
| | 5 | | using System.ComponentModel; |
| | 6 | | using System.Diagnostics; |
| | 7 | |
|
| | 8 | | namespace Ice; |
| | 9 | |
|
| | 10 | | /// <summary> |
| | 11 | | /// The base interface for servants. |
| | 12 | | /// </summary> |
| | 13 | | [SliceTypeId("::Ice::Object")] |
| | 14 | | public interface Object |
| | 15 | | { |
| | 16 | | /// <summary> |
| | 17 | | /// Dispatches an incoming request and returns the corresponding outgoing response. |
| | 18 | | /// </summary> |
| | 19 | | /// <param name="request">The incoming request.</param> |
| | 20 | | /// <returns>A value task that holds the outgoing response.</returns> |
| | 21 | | /// <remarks>Ice marshals any exception thrown by this method into the response.</remarks> |
| | 22 | | public ValueTask<OutgoingResponse> dispatchAsync(IncomingRequest request) => |
| | 23 | | request.current.operation switch |
| | 24 | | { |
| | 25 | | "ice_id" => iceD_ice_idAsync(this, request), |
| | 26 | | "ice_ids" => iceD_ice_idsAsync(this, request), |
| | 27 | | "ice_isA" => iceD_ice_isAAsync(this, request), |
| | 28 | | "ice_ping" => iceD_ice_pingAsync(this, request), |
| | 29 | | _ => throw new OperationNotExistException() |
| | 30 | | }; |
| | 31 | |
|
| | 32 | | /// <summary> |
| | 33 | | /// Tests whether this object supports a specific Slice interface. |
| | 34 | | /// </summary> |
| | 35 | | /// |
| | 36 | | /// <param name="s">The type ID of the Slice interface to test against.</param> |
| | 37 | | /// <param name="current">The Current object for the dispatch.</param> |
| | 38 | | /// <returns>True if this object has the interface |
| | 39 | | /// specified by s or derives from the interface specified by s.</returns> |
| | 40 | | public bool ice_isA(string s, Current current) |
| | 41 | | { |
| | 42 | | foreach (Type type in GetType().GetInterfaces()) |
| | 43 | | { |
| | 44 | | if (type.GetSliceTypeId() is string typeId && typeId == s) |
| | 45 | | { |
| | 46 | | return true; |
| | 47 | | } |
| | 48 | | } |
| | 49 | | return false; |
| | 50 | | } |
| | 51 | |
|
| | 52 | | /// <summary> |
| | 53 | | /// Tests whether this object can be reached. |
| | 54 | | /// </summary> |
| | 55 | | /// <param name="current">The Current object for the dispatch.</param> |
| | 56 | | public void ice_ping(Current current) |
| | 57 | | { |
| | 58 | | // does nothing |
| | 59 | | } |
| | 60 | |
|
| | 61 | | /// <summary> |
| | 62 | | /// Gets the Slice type IDs of the interfaces supported by this object. |
| | 63 | | /// </summary> |
| | 64 | | /// <param name="current">The Current object for the dispatch.</param> |
| | 65 | | /// <returns>The Slice type IDs of the interfaces supported by this object, in alphabetical order.</returns> |
| | 66 | | public string[] ice_ids(Current current) |
| | 67 | | { |
| | 68 | | var sortedSet = new SortedSet<string>(StringComparer.Ordinal); |
| | 69 | | foreach (Type type in GetType().GetInterfaces()) |
| | 70 | | { |
| | 71 | | if (type.GetSliceTypeId() is string typeId) |
| | 72 | | { |
| | 73 | | sortedSet.Add(typeId); |
| | 74 | | } |
| | 75 | | } |
| | 76 | | return sortedSet.ToArray(); |
| | 77 | | } |
| | 78 | |
|
| | 79 | | /// <summary> |
| | 80 | | /// Gets the Slice type ID of the most-derived interface supported by this object. |
| | 81 | | /// </summary> |
| | 82 | | /// <param name="current">The Current object for the dispatch.</param> |
| | 83 | | /// <returns>The Slice type ID of the most-derived interface.</returns> |
| | 84 | | public string ice_id(Current current) => ice_staticId(); |
| | 85 | |
|
| | 86 | | /// <summary> |
| | 87 | | /// Gets the Slice type ID of the interface supported by this object. |
| | 88 | | /// </summary> |
| | 89 | | /// <returns>The return value is always ::Ice::Object.</returns> |
| | 90 | | public static string ice_staticId() => "::Ice::Object"; |
| | 91 | |
|
| | 92 | | [EditorBrowsable(EditorBrowsableState.Never)] |
| | 93 | | protected static ValueTask<OutgoingResponse> iceD_ice_isAAsync(Object obj, IncomingRequest request) |
| | 94 | | { |
| | 95 | | InputStream istr = request.inputStream; |
| | 96 | | istr.startEncapsulation(); |
| | 97 | | string iceP_id = istr.readString(); |
| | 98 | | istr.endEncapsulation(); |
| | 99 | | bool ret = obj.ice_isA(iceP_id, request.current); |
| | 100 | | return new(request.current.createOutgoingResponse(ret, static (ostr, ret) => ostr.writeBool(ret))); |
| | 101 | | } |
| | 102 | |
|
| | 103 | | [EditorBrowsable(EditorBrowsableState.Never)] |
| | 104 | | protected static ValueTask<OutgoingResponse> iceD_ice_pingAsync(Object obj, IncomingRequest request) |
| | 105 | | { |
| | 106 | | InputStream istr = request.inputStream; |
| | 107 | | istr.skipEmptyEncapsulation(); |
| | 108 | | obj.ice_ping(request.current); |
| | 109 | | return new(request.current.createEmptyOutgoingResponse()); |
| | 110 | | } |
| | 111 | |
|
| | 112 | | [EditorBrowsable(EditorBrowsableState.Never)] |
| | 113 | | protected static ValueTask<OutgoingResponse> iceD_ice_idsAsync(Object obj, IncomingRequest request) |
| | 114 | | { |
| | 115 | | InputStream istr = request.inputStream; |
| | 116 | | istr.skipEmptyEncapsulation(); |
| | 117 | | string[] ret = obj.ice_ids(request.current); |
| | 118 | | return new(request.current.createOutgoingResponse(ret, static (ostr, ret) => ostr.writeStringSeq(ret))); |
| | 119 | | } |
| | 120 | |
|
| | 121 | | [EditorBrowsable(EditorBrowsableState.Never)] |
| | 122 | | protected static ValueTask<OutgoingResponse> iceD_ice_idAsync(Object obj, IncomingRequest request) |
| | 123 | | { |
| | 124 | | InputStream istr = request.inputStream; |
| | 125 | | istr.skipEmptyEncapsulation(); |
| | 126 | | string ret = obj.ice_id(request.current); |
| | 127 | | return new(request.current.createOutgoingResponse(ret, static (ostr, ret) => ostr.writeString(ret))); |
| | 128 | | } |
| | 129 | | } |
| | 130 | |
|
| | 131 | | /// <summary> |
| | 132 | | /// Base class for dynamic dispatch servants. A server application |
| | 133 | | /// derives a concrete servant class from Blobject that |
| | 134 | | /// implements the Blobject.ice_invoke method. |
| | 135 | | /// </summary> |
| | 136 | | public abstract class Blobject : Object |
| | 137 | | { |
| | 138 | | /// <summary> |
| | 139 | | /// Dispatch an incoming request. |
| | 140 | | /// </summary> |
| | 141 | | /// <param name="inParams">The encoded in-parameters for the operation.</param> |
| | 142 | | /// <param name="outParams">The encoded out-parameters and return value |
| | 143 | | /// for the operation. The return value follows any out-parameters.</param> |
| | 144 | | /// <param name="current">The Current object to pass to the operation.</param> |
| | 145 | | /// <returns>If the operation completed successfully, the return value |
| | 146 | | /// is true. If the operation raises a user exception, |
| | 147 | | /// the return value is false; in this case, outParams |
| | 148 | | /// must contain the encoded user exception. If the operation raises an |
| | 149 | | /// Ice run-time exception, it must throw it directly.</returns> |
| | 150 | | public abstract bool ice_invoke(byte[] inParams, out byte[] outParams, Current current); |
| | 151 | |
|
| | 152 | | public ValueTask<OutgoingResponse> dispatchAsync(IncomingRequest request) |
| | 153 | | { |
| 1 | 154 | | byte[] inEncaps = request.inputStream.readEncapsulation(out _); |
| 1 | 155 | | bool ok = ice_invoke(inEncaps, out byte[] outEncaps, request.current); |
| 1 | 156 | | return new(request.current.createOutgoingResponse(ok, outEncaps)); |
| | 157 | | } |
| | 158 | | } |
| | 159 | |
|
| | 160 | | public abstract class BlobjectAsync : Object |
| | 161 | | { |
| | 162 | | public abstract Task<Object_Ice_invokeResult> ice_invokeAsync(byte[] inEncaps, Current current); |
| | 163 | |
|
| | 164 | | public async ValueTask<OutgoingResponse> dispatchAsync(IncomingRequest request) |
| | 165 | | { |
| | 166 | | byte[] inEncaps = request.inputStream.readEncapsulation(out _); |
| | 167 | | Object_Ice_invokeResult result = await ice_invokeAsync(inEncaps, request.current).ConfigureAwait(false); |
| | 168 | | return request.current.createOutgoingResponse(result.returnValue, result.outEncaps); |
| | 169 | | } |
| | 170 | | } |