Out with MagicOnion, in with LiteNetLib
Removed MagicOnion Added LiteNetLib Created client and server abstractions Fixed serialization bugs
This commit is contained in:
parent
433a7b4ae4
commit
e96146b7bb
869 changed files with 59401 additions and 16812 deletions
469
.idea/.idea.Aetheria-Economy/.idea/contentModel.xml
generated
469
.idea/.idea.Aetheria-Economy/.idea/contentModel.xml
generated
|
|
@ -46,7 +46,7 @@
|
|||
</e>
|
||||
</e>
|
||||
<e p="Scripts" t="Include">
|
||||
<e p="ChatComponent.cs" t="Include" />
|
||||
<e p="CultClient.cs" t="Include" />
|
||||
<e p="Editor" t="Include">
|
||||
<e p="DatabaseInspector.cs" t="Include" />
|
||||
<e p="DatabaseView.cs" t="Include" />
|
||||
|
|
@ -55,10 +55,6 @@
|
|||
<e p="SerializerTestWindow.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Galaxy.cs" t="Include" />
|
||||
<e p="Generated" t="Include">
|
||||
<e p="MagicOnion.Generated.cs" t="Include" />
|
||||
<e p="MessagePack.Generated.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Icons.cs" t="Include" />
|
||||
<e p="InitialSettings.cs" t="Include" />
|
||||
<e p="MarkovNameGenerator.cs" t="Include" />
|
||||
|
|
@ -107,70 +103,6 @@
|
|||
<e p="WhereSum.cs" t="Include" />
|
||||
<e p="Zip.cs" t="Include" />
|
||||
</e>
|
||||
<e p="MagicOnion" t="Include">
|
||||
<e p="AsyncLock.cs" t="Include" />
|
||||
<e p="AsyncStreamReaderExtensions.cs" t="Include" />
|
||||
<e p="Client" t="Include">
|
||||
<e p="ClientFilter.cs" t="Include" />
|
||||
<e p="DynamicClientBuilder.cs" t="Include" />
|
||||
<e p="InterceptInvokeHelper.cs" t="Include" />
|
||||
<e p="MagicOnionClient.cs" t="Include" />
|
||||
<e p="MagicOnionClientBase.cs" t="Include" />
|
||||
<e p="StreamingHubClient.cs" t="Include" />
|
||||
<e p="StreamingHubClientBase.cs" t="Include" />
|
||||
<e p="StreamingHubClientBuilder.cs" t="Include" />
|
||||
</e>
|
||||
<e p="DynamicArgumentTuple.cs" t="Include" />
|
||||
<e p="MagicOnion.asmdef" t="Include" />
|
||||
<e p="MagicOnionMarshallers.cs" t="Include" />
|
||||
<e p="MetadataExtensions.cs" t="Include" />
|
||||
<e p="ReturnStatusException.cs" t="Include" />
|
||||
<e p="Server" t="Include">
|
||||
<e p="Hubs" t="Include">
|
||||
<e p="BroadcasterHelper.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="UnsafeDirectBlitResolver.cs" t="Include" />
|
||||
<e p="Utils" t="Include">
|
||||
<e p="ArrayPoolBufferWriter.cs" t="Include" />
|
||||
<e p="AsyncLocalShim.cs" t="Include" />
|
||||
<e p="DynamicAssembly.cs" t="Include" />
|
||||
<e p="FNV1A32.cs" t="Include" />
|
||||
<e p="ILGeneratorExtensions.cs" t="Include" />
|
||||
<e p="ReflectionExtensions.cs" t="Include" />
|
||||
<e p="ReservedWhenAllPromise.cs" t="Include" />
|
||||
<e p="TaskCompletionSourceEx.cs" t="Include" />
|
||||
<e p="TaskEx.cs" t="Include" />
|
||||
<e p="UniqueHashDictionary.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="MagicOnion.Abstractions" t="Include">
|
||||
<e p="Client" t="Include">
|
||||
<e p="IResponseContext.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ClientStreamingResult.cs" t="Include" />
|
||||
<e p="CompilerServices" t="Include">
|
||||
<e p="AsyncUnaryResultMethodBuilder.cs" t="Include" />
|
||||
</e>
|
||||
<e p="DuplexStreamingResult.cs" t="Include" />
|
||||
<e p="GenerateDefineDebugAttribute.cs" t="Include" />
|
||||
<e p="IgnoreAttribute.cs" t="Include" />
|
||||
<e p="IService.cs" t="Include" />
|
||||
<e p="IStreamingHub.cs" t="Include" />
|
||||
<e p="MagicOnion.Abstractions.asmdef" t="Include" />
|
||||
<e p="Server" t="Include">
|
||||
<e p="Hubs" t="Include">
|
||||
<e p="MethodIdAttribute.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="ServerStreamingResult.cs" t="Include" />
|
||||
<e p="UnaryResult.cs" t="Include" />
|
||||
</e>
|
||||
<e p="MagicOnion.Unity" t="Include">
|
||||
<e p="ChannelExtensions.cs" t="Include" />
|
||||
<e p="MagicOnion.Unity.asmdef" t="Include" />
|
||||
<e p="UnityDebugLogger.cs" t="Include" />
|
||||
</e>
|
||||
<e p="MessagePack" t="Include">
|
||||
<e p="Annotations" t="Include">
|
||||
<e p="Attributes.cs" t="Include" />
|
||||
|
|
@ -725,6 +657,7 @@
|
|||
<e p="Prototype.cs" t="Include" />
|
||||
<e p="Scr_Log_In.cs" t="Include" />
|
||||
<e p="ServerShared" t="Include">
|
||||
<e p="ActionCollection.cs" t="Include" />
|
||||
<e p="Attributes.cs" t="Include" />
|
||||
<e p="DatabaseCache.cs" t="Include" />
|
||||
<e p="DatabaseItems.cs" t="Include" />
|
||||
|
|
@ -733,10 +666,6 @@
|
|||
<e p="Extensions.cs" t="Include" />
|
||||
<e p="GameContext.cs" t="Include" />
|
||||
<e p="GlobalData.cs" t="Include" />
|
||||
<e p="Hubs" t="Include">
|
||||
<e p="IChatHub.cs" t="Include" />
|
||||
<e p="IChatHubReceiver.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ItemBehaviors" t="Include">
|
||||
<e p="Afterburner.cs" t="Include" />
|
||||
<e p="Behaviors.cs" t="Include" />
|
||||
|
|
@ -750,10 +679,7 @@
|
|||
<e p="JsonConverters.cs" t="Include" />
|
||||
<e p="MathFormatters.cs" t="Include" />
|
||||
<e p="MathResolver.cs" t="Include" />
|
||||
<e p="MessagePackObjects" t="Include">
|
||||
<e p="Requests.cs" t="Include" />
|
||||
<e p="Responses.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Messages.cs" t="Include" />
|
||||
<e p="NIH" t="Include">
|
||||
<e p="JsonKnownTypes" t="Include">
|
||||
<e p="AttributesManager.cs" t="Include" />
|
||||
|
|
@ -773,11 +699,391 @@
|
|||
<e p="Mapper.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="LiteNetLib" t="Include">
|
||||
<e p="BaseChannel.cs" t="Include" />
|
||||
<e p="ConnectionRequest.cs" t="Include" />
|
||||
<e p="INetEventListener.cs" t="Include" />
|
||||
<e p="Layers" t="Include">
|
||||
<e p="Crc32cLayer.cs" t="Include" />
|
||||
<e p="PacketLayerBase.cs" t="Include" />
|
||||
<e p="XorEncryptLayer.cs" t="Include" />
|
||||
</e>
|
||||
<e p="NatPunchModule.cs" t="Include" />
|
||||
<e p="NetConstants.cs" t="Include" />
|
||||
<e p="NetDebug.cs" t="Include" />
|
||||
<e p="NetExceptions.cs" t="Include" />
|
||||
<e p="NetManager.cs" t="Include" />
|
||||
<e p="NetPacket.cs" t="Include" />
|
||||
<e p="NetPacketPool.cs" t="Include" />
|
||||
<e p="NetPeer.cs" t="Include" />
|
||||
<e p="NetSocket.cs" t="Include" />
|
||||
<e p="NetStatistics.cs" t="Include" />
|
||||
<e p="NetUtils.cs" t="Include" />
|
||||
<e p="ReliableChannel.cs" t="Include" />
|
||||
<e p="SequencedChannel.cs" t="Include" />
|
||||
<e p="Utils" t="Include">
|
||||
<e p="CRC32C.cs" t="Include" />
|
||||
<e p="FastBitConverter.cs" t="Include" />
|
||||
<e p="INetSerializable.cs" t="Include" />
|
||||
<e p="NetDataReader.cs" t="Include" />
|
||||
<e p="NetDataWriter.cs" t="Include" />
|
||||
<e p="NetPacketProcessor.cs" t="Include" />
|
||||
<e p="NetSerializer.cs" t="Include" />
|
||||
<e p="NtpPacket.cs" t="Include" />
|
||||
<e p="NtpRequest.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="RethinkDb.Driver" t="Include">
|
||||
<e p="Ast" t="Include">
|
||||
<e p="ExtensionHelper.cs" t="Include" />
|
||||
<e p="Poco.cs" t="Include" />
|
||||
<e p="PropertyHelper.cs" t="Include" />
|
||||
<e p="Query.cs" t="Include" />
|
||||
<e p="ReqlAst.cs" t="Include" />
|
||||
<e p="ReqlExpr.cs" t="Include" />
|
||||
<e p="ReqlRaw.cs" t="Include" />
|
||||
<e p="TopLevel.cs" t="Include" />
|
||||
<e p="Util.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ErrorBuilder.cs" t="Include" />
|
||||
<e p="Extras" t="Include">
|
||||
<e p="Dao" t="Include">
|
||||
<e p="Document.cs" t="Include" />
|
||||
<e p="IDao.cs" t="Include" />
|
||||
<e p="RethinkDao.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="Generated" t="Include">
|
||||
<e p="Ast" t="Include">
|
||||
<e p="Add.cs" t="Include" />
|
||||
<e p="And.cs" t="Include" />
|
||||
<e p="Append.cs" t="Include" />
|
||||
<e p="April.cs" t="Include" />
|
||||
<e p="Args.cs" t="Include" />
|
||||
<e p="Asc.cs" t="Include" />
|
||||
<e p="August.cs" t="Include" />
|
||||
<e p="Avg.cs" t="Include" />
|
||||
<e p="Between.cs" t="Include" />
|
||||
<e p="Binary.cs" t="Include" />
|
||||
<e p="Bracket.cs" t="Include" />
|
||||
<e p="Branch.cs" t="Include" />
|
||||
<e p="Ceil.cs" t="Include" />
|
||||
<e p="ChangeAt.cs" t="Include" />
|
||||
<e p="Changes.cs" t="Include" />
|
||||
<e p="Circle.cs" t="Include" />
|
||||
<e p="CoerceTo.cs" t="Include" />
|
||||
<e p="ConcatMap.cs" t="Include" />
|
||||
<e p="Config.cs" t="Include" />
|
||||
<e p="Contains.cs" t="Include" />
|
||||
<e p="Count.cs" t="Include" />
|
||||
<e p="Date.cs" t="Include" />
|
||||
<e p="Datum.cs" t="Include" />
|
||||
<e p="Day.cs" t="Include" />
|
||||
<e p="DayOfWeek.cs" t="Include" />
|
||||
<e p="DayOfYear.cs" t="Include" />
|
||||
<e p="Db.cs" t="Include" />
|
||||
<e p="DbCreate.cs" t="Include" />
|
||||
<e p="DbDrop.cs" t="Include" />
|
||||
<e p="DbList.cs" t="Include" />
|
||||
<e p="December.cs" t="Include" />
|
||||
<e p="Default.cs" t="Include" />
|
||||
<e p="Delete.cs" t="Include" />
|
||||
<e p="DeleteAt.cs" t="Include" />
|
||||
<e p="Desc.cs" t="Include" />
|
||||
<e p="Difference.cs" t="Include" />
|
||||
<e p="Distance.cs" t="Include" />
|
||||
<e p="Distinct.cs" t="Include" />
|
||||
<e p="Div.cs" t="Include" />
|
||||
<e p="Downcase.cs" t="Include" />
|
||||
<e p="During.cs" t="Include" />
|
||||
<e p="EpochTime.cs" t="Include" />
|
||||
<e p="Eq.cs" t="Include" />
|
||||
<e p="EqJoin.cs" t="Include" />
|
||||
<e p="Error.cs" t="Include" />
|
||||
<e p="February.cs" t="Include" />
|
||||
<e p="Fill.cs" t="Include" />
|
||||
<e p="Filter.cs" t="Include" />
|
||||
<e p="Floor.cs" t="Include" />
|
||||
<e p="Fold.cs" t="Include" />
|
||||
<e p="ForEach.cs" t="Include" />
|
||||
<e p="Friday.cs" t="Include" />
|
||||
<e p="Func.cs" t="Include" />
|
||||
<e p="Funcall.cs" t="Include" />
|
||||
<e p="Ge.cs" t="Include" />
|
||||
<e p="Geojson.cs" t="Include" />
|
||||
<e p="Get.cs" t="Include" />
|
||||
<e p="GetAll.cs" t="Include" />
|
||||
<e p="GetField.cs" t="Include" />
|
||||
<e p="GetIntersecting.cs" t="Include" />
|
||||
<e p="GetNearest.cs" t="Include" />
|
||||
<e p="Grant.cs" t="Include" />
|
||||
<e p="Group.cs" t="Include" />
|
||||
<e p="Gt.cs" t="Include" />
|
||||
<e p="HasFields.cs" t="Include" />
|
||||
<e p="Hours.cs" t="Include" />
|
||||
<e p="Http.cs" t="Include" />
|
||||
<e p="Includes.cs" t="Include" />
|
||||
<e p="IndexCreate.cs" t="Include" />
|
||||
<e p="IndexDrop.cs" t="Include" />
|
||||
<e p="IndexList.cs" t="Include" />
|
||||
<e p="IndexRename.cs" t="Include" />
|
||||
<e p="IndexStatus.cs" t="Include" />
|
||||
<e p="IndexWait.cs" t="Include" />
|
||||
<e p="Info.cs" t="Include" />
|
||||
<e p="InnerJoin.cs" t="Include" />
|
||||
<e p="Insert.cs" t="Include" />
|
||||
<e p="InsertAt.cs" t="Include" />
|
||||
<e p="Intersects.cs" t="Include" />
|
||||
<e p="InTimezone.cs" t="Include" />
|
||||
<e p="IsEmpty.cs" t="Include" />
|
||||
<e p="Iso8601.cs" t="Include" />
|
||||
<e p="January.cs" t="Include" />
|
||||
<e p="Javascript.cs" t="Include" />
|
||||
<e p="Json.cs" t="Include" />
|
||||
<e p="July.cs" t="Include" />
|
||||
<e p="June.cs" t="Include" />
|
||||
<e p="Keys.cs" t="Include" />
|
||||
<e p="Le.cs" t="Include" />
|
||||
<e p="Limit.cs" t="Include" />
|
||||
<e p="Line.cs" t="Include" />
|
||||
<e p="Literal.cs" t="Include" />
|
||||
<e p="Lt.cs" t="Include" />
|
||||
<e p="MakeArray.cs" t="Include" />
|
||||
<e p="MakeObj.cs" t="Include" />
|
||||
<e p="Map.cs" t="Include" />
|
||||
<e p="March.cs" t="Include" />
|
||||
<e p="Match.cs" t="Include" />
|
||||
<e p="Max.cs" t="Include" />
|
||||
<e p="Maxval.cs" t="Include" />
|
||||
<e p="May.cs" t="Include" />
|
||||
<e p="Merge.cs" t="Include" />
|
||||
<e p="Min.cs" t="Include" />
|
||||
<e p="Minutes.cs" t="Include" />
|
||||
<e p="Minval.cs" t="Include" />
|
||||
<e p="Mod.cs" t="Include" />
|
||||
<e p="Monday.cs" t="Include" />
|
||||
<e p="Month.cs" t="Include" />
|
||||
<e p="Mul.cs" t="Include" />
|
||||
<e p="Ne.cs" t="Include" />
|
||||
<e p="Not.cs" t="Include" />
|
||||
<e p="November.cs" t="Include" />
|
||||
<e p="Now.cs" t="Include" />
|
||||
<e p="Nth.cs" t="Include" />
|
||||
<e p="October.cs" t="Include" />
|
||||
<e p="OffsetsOf.cs" t="Include" />
|
||||
<e p="Or.cs" t="Include" />
|
||||
<e p="OrderBy.cs" t="Include" />
|
||||
<e p="OuterJoin.cs" t="Include" />
|
||||
<e p="Pluck.cs" t="Include" />
|
||||
<e p="Point.cs" t="Include" />
|
||||
<e p="Polygon.cs" t="Include" />
|
||||
<e p="PolygonSub.cs" t="Include" />
|
||||
<e p="Prepend.cs" t="Include" />
|
||||
<e p="Random.cs" t="Include" />
|
||||
<e p="Range.cs" t="Include" />
|
||||
<e p="Rebalance.cs" t="Include" />
|
||||
<e p="Reconfigure.cs" t="Include" />
|
||||
<e p="Reduce.cs" t="Include" />
|
||||
<e p="Replace.cs" t="Include" />
|
||||
<e p="ReqlExpr.cs" t="Include" />
|
||||
<e p="ReqlObject.cs" t="Include" />
|
||||
<e p="Round.cs" t="Include" />
|
||||
<e p="Sample.cs" t="Include" />
|
||||
<e p="Saturday.cs" t="Include" />
|
||||
<e p="Seconds.cs" t="Include" />
|
||||
<e p="September.cs" t="Include" />
|
||||
<e p="SetDifference.cs" t="Include" />
|
||||
<e p="SetInsert.cs" t="Include" />
|
||||
<e p="SetIntersection.cs" t="Include" />
|
||||
<e p="SetUnion.cs" t="Include" />
|
||||
<e p="Skip.cs" t="Include" />
|
||||
<e p="Slice.cs" t="Include" />
|
||||
<e p="SpliceAt.cs" t="Include" />
|
||||
<e p="Split.cs" t="Include" />
|
||||
<e p="Status.cs" t="Include" />
|
||||
<e p="Sub.cs" t="Include" />
|
||||
<e p="Sum.cs" t="Include" />
|
||||
<e p="Sunday.cs" t="Include" />
|
||||
<e p="Sync.cs" t="Include" />
|
||||
<e p="Table.cs" t="Include" />
|
||||
<e p="TableCreate.cs" t="Include" />
|
||||
<e p="TableDrop.cs" t="Include" />
|
||||
<e p="TableList.cs" t="Include" />
|
||||
<e p="Thursday.cs" t="Include" />
|
||||
<e p="Time.cs" t="Include" />
|
||||
<e p="TimeOfDay.cs" t="Include" />
|
||||
<e p="Timezone.cs" t="Include" />
|
||||
<e p="ToEpochTime.cs" t="Include" />
|
||||
<e p="ToGeojson.cs" t="Include" />
|
||||
<e p="ToIso8601.cs" t="Include" />
|
||||
<e p="ToJsonString.cs" t="Include" />
|
||||
<e p="Tuesday.cs" t="Include" />
|
||||
<e p="TypeOf.cs" t="Include" />
|
||||
<e p="Ungroup.cs" t="Include" />
|
||||
<e p="Union.cs" t="Include" />
|
||||
<e p="Upcase.cs" t="Include" />
|
||||
<e p="Update.cs" t="Include" />
|
||||
<e p="Uuid.cs" t="Include" />
|
||||
<e p="Values.cs" t="Include" />
|
||||
<e p="Var.cs" t="Include" />
|
||||
<e p="Wait.cs" t="Include" />
|
||||
<e p="Wednesday.cs" t="Include" />
|
||||
<e p="WithFields.cs" t="Include" />
|
||||
<e p="Without.cs" t="Include" />
|
||||
<e p="Year.cs" t="Include" />
|
||||
<e p="Zip.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Model" t="Include">
|
||||
<e p="AuthType.cs" t="Include" />
|
||||
<e p="Bound.cs" t="Include" />
|
||||
<e p="Conflict.cs" t="Include" />
|
||||
<e p="Durability.cs" t="Include" />
|
||||
<e p="EmergencyRepair.cs" t="Include" />
|
||||
<e p="Format.cs" t="Include" />
|
||||
<e p="GeoSystem.cs" t="Include" />
|
||||
<e p="HttpMethod.cs" t="Include" />
|
||||
<e p="IdentifierFormat.cs" t="Include" />
|
||||
<e p="ReadMode.cs" t="Include" />
|
||||
<e p="ReqlFunction0.cs" t="Include" />
|
||||
<e p="ReqlFunction1.cs" t="Include" />
|
||||
<e p="ReqlFunction2.cs" t="Include" />
|
||||
<e p="ReqlFunction3.cs" t="Include" />
|
||||
<e p="ReqlFunction4.cs" t="Include" />
|
||||
<e p="ResultFormat.cs" t="Include" />
|
||||
<e p="Status.cs" t="Include" />
|
||||
<e p="TopLevel.cs" t="Include" />
|
||||
<e p="Unit.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Proto" t="Include">
|
||||
<e p="DatumType.cs" t="Include" />
|
||||
<e p="ErrorType.cs" t="Include" />
|
||||
<e p="FrameType.cs" t="Include" />
|
||||
<e p="Protocol.cs" t="Include" />
|
||||
<e p="QueryType.cs" t="Include" />
|
||||
<e p="ResponseNote.cs" t="Include" />
|
||||
<e p="ResponseType.cs" t="Include" />
|
||||
<e p="TermType.cs" t="Include" />
|
||||
<e p="Version.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ReqlAuthError.cs" t="Include" />
|
||||
<e p="ReqlAvailabilityError.cs" t="Include" />
|
||||
<e p="ReqlClientError.cs" t="Include" />
|
||||
<e p="ReqlCompileError.cs" t="Include" />
|
||||
<e p="ReqlDriverCompileError.cs" t="Include" />
|
||||
<e p="ReqlDriverError.cs" t="Include" />
|
||||
<e p="ReqlError.cs" t="Include" />
|
||||
<e p="ReqlInternalError.cs" t="Include" />
|
||||
<e p="ReqlNonExistenceError.cs" t="Include" />
|
||||
<e p="ReqlOpFailedError.cs" t="Include" />
|
||||
<e p="ReqlOpIndeterminateError.cs" t="Include" />
|
||||
<e p="ReqlPermissionError.cs" t="Include" />
|
||||
<e p="ReqlQueryLogicError.cs" t="Include" />
|
||||
<e p="ReqlResourceLimitError.cs" t="Include" />
|
||||
<e p="ReqlRuntimeError.cs" t="Include" />
|
||||
<e p="ReqlServerCompileError.cs" t="Include" />
|
||||
<e p="ReqlUserError.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Log.cs" t="Include" />
|
||||
<e p="Model" t="Include">
|
||||
<e p="Arguments.cs" t="Include" />
|
||||
<e p="Backtrace.cs" t="Include" />
|
||||
<e p="Change[T].cs" t="Include" />
|
||||
<e p="ExtensionsForResult.cs" t="Include" />
|
||||
<e p="GroupedResult.cs" t="Include" />
|
||||
<e p="MapObject.cs" t="Include" />
|
||||
<e p="OptArgs.cs" t="Include" />
|
||||
<e p="PathSpec.cs" t="Include" />
|
||||
<e p="Profile.cs" t="Include" />
|
||||
<e p="ReqlLambda.cs" t="Include" />
|
||||
<e p="Result.cs" t="Include" />
|
||||
<e p="Server.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Net" t="Include">
|
||||
<e p="Awaiter.cs" t="Include" />
|
||||
<e p="Clustering" t="Include">
|
||||
<e p="ConnectionPool.cs" t="Include" />
|
||||
<e p="EpsilonGreedy.cs" t="Include" />
|
||||
<e p="EpsilonValueCalculator.cs" t="Include" />
|
||||
<e p="ExceptionIs.cs" t="Include" />
|
||||
<e p="HostEntry.cs" t="Include" />
|
||||
<e p="HostPool.cs" t="Include" />
|
||||
<e p="IPoolingStrategy.cs" t="Include" />
|
||||
<e p="RoundRobinHostPool.cs" t="Include" />
|
||||
<e p="Seed.cs" t="Include" />
|
||||
<e p="Server.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Connection.cs" t="Include" />
|
||||
<e p="Converter.cs" t="Include" />
|
||||
<e p="Crypto.cs" t="Include" />
|
||||
<e p="Cursor.cs" t="Include" />
|
||||
<e p="FormatOptions.cs" t="Include" />
|
||||
<e p="Handshake.cs" t="Include" />
|
||||
<e p="IConnection.cs" t="Include" />
|
||||
<e p="IConnectionBuilder.cs" t="Include" />
|
||||
<e p="ICursor.cs" t="Include" />
|
||||
<e p="IncrementalSHA256.cs" t="Include" />
|
||||
<e p="JsonConverters" t="Include">
|
||||
<e p="ExtensionsForJsonConverters.cs" t="Include" />
|
||||
<e p="ReqlBinaryConverter.cs" t="Include" />
|
||||
<e p="ReqlDateTimeConverter.cs" t="Include" />
|
||||
<e p="ReqlExprConverter.cs" t="Include" />
|
||||
<e p="ReqlGroupingConverter.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Response.cs" t="Include" />
|
||||
<e p="ScramAttributes.cs" t="Include" />
|
||||
<e p="SecureRandom.cs" t="Include" />
|
||||
<e p="SocketWrapper.cs" t="Include" />
|
||||
<e p="SslContext.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ReqlAssertFailure.cs" t="Include" />
|
||||
<e p="RethinkDB.cs" t="Include" />
|
||||
<e p="RethinkDBConstants.cs" t="Include" />
|
||||
<e p="Utils" t="Include">
|
||||
<e p="CancellableTask.cs" t="Include" />
|
||||
<e p="ExtensionsForEvent.cs" t="Include" />
|
||||
<e p="ExtensionsForString.cs" t="Include" />
|
||||
<e p="ExtensionsForTcpClient.cs" t="Include" />
|
||||
<e p="ExtensionsForType.cs" t="Include" />
|
||||
<e p="QueryHelper.cs" t="Include" />
|
||||
<e p="StringHelper.cs" t="Include" />
|
||||
<e p="TaskHelper.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="RethinkDb.Driver.Linq" t="Include">
|
||||
<e p="Attributes" t="Include">
|
||||
<e p="PrimaryIndexAttribute.cs" t="Include" />
|
||||
<e p="SecondaryIndexAttribute.cs" t="Include" />
|
||||
</e>
|
||||
<e p="LinqExtensions.cs" t="Include" />
|
||||
<e p="MemberNameResolver.cs" t="Include" />
|
||||
<e p="RethinkDbGroup.cs" t="Include" />
|
||||
<e p="RethinkDbQueryModelVisitor.cs" t="Include" />
|
||||
<e p="RethinkQueryable.cs" t="Include" />
|
||||
<e p="RethinkQueryExecutor.cs" t="Include" />
|
||||
<e p="SelectionProjector.cs" t="Include" />
|
||||
<e p="WhereClauseParsers" t="Include">
|
||||
<e p="BaseIndexParser.cs" t="Include" />
|
||||
<e p="DefaultParser.cs" t="Include" />
|
||||
<e p="ExpressionVisitor.cs" t="Include" />
|
||||
<e p="ExprHelper.cs" t="Include" />
|
||||
<e p="GroupItemsParser.cs" t="Include" />
|
||||
<e p="IWhereClauseParser.cs" t="Include" />
|
||||
<e p="PrimaryIndexParser.cs" t="Include" />
|
||||
<e p="SecondaryIndexParser.cs" t="Include" />
|
||||
<e p="SubQueryVisitor" t="Include">
|
||||
<e p="AllSubQueryVisitor.cs" t="Include" />
|
||||
<e p="AnySubQueryVisitor.cs" t="Include" />
|
||||
<e p="BaseFilterableSubQueryVisitor.cs" t="Include" />
|
||||
<e p="BaseSubQueryVisitor.cs" t="Include" />
|
||||
<e p="ContainsSubQueryVisitor.cs" t="Include" />
|
||||
<e p="CountSubQueryVisitor.cs" t="Include" />
|
||||
<e p="FirstSubQueryVisitor.cs" t="Include" />
|
||||
<e p="ISubQueryVisitor.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
</e>
|
||||
</e>
|
||||
<e p="OrbitInstance.cs" t="Include" />
|
||||
<e p="Services" t="Include">
|
||||
<e p="IChatService.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Ship.cs" t="Include" />
|
||||
<e p="ZoneData.cs" t="Include" />
|
||||
<e p="ZoneGenerator.cs" t="Include" />
|
||||
|
|
@ -797,9 +1103,6 @@
|
|||
</e>
|
||||
</e>
|
||||
<e p="Economy.Shared.Unity.csproj" t="IncludeRecursive" />
|
||||
<e p="MagicOnion.Abstractions.csproj" t="IncludeRecursive" />
|
||||
<e p="MagicOnion.csproj" t="IncludeRecursive" />
|
||||
<e p="MagicOnion.Unity.csproj" t="IncludeRecursive" />
|
||||
<e p="MessagePack.csproj" t="IncludeRecursive" />
|
||||
<e p="obj" t="ExcludeRecursive" />
|
||||
<e p="Packages" t="ExcludeRecursive" />
|
||||
|
|
|
|||
444
.idea/.idea.Economy/.idea/contentModel.xml
generated
444
.idea/.idea.Economy/.idea/contentModel.xml
generated
|
|
@ -4,6 +4,7 @@
|
|||
<e p="C:\Users\rwvens\.Rider2019.3\system\extResources" t="IncludeRecursive" />
|
||||
<e p="C:\Users\rwvens\.Rider2019.3\system\resharper-host\local\Transient\ReSharperHost\v193\SolutionCaches\_Economy.820823087.00" t="ExcludeRecursive" />
|
||||
<e p="C:\Users\rwvens\Documents\GitHub\Aetheria-Economy" t="IncludeFlat">
|
||||
<e p="Assets\Scripts\ServerShared\ActionCollection.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\Attributes.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\DatabaseCache.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\DatabaseItems.cs" t="Include" />
|
||||
|
|
@ -11,46 +12,430 @@
|
|||
<e p="Assets\Scripts\ServerShared\Extensions.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\GameContext.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\GlobalData.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\Hubs" t="Include">
|
||||
<e p="IChatHub.cs" t="Include" />
|
||||
<e p="IChatHubReceiver.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ItemBehaviors" t="Include">
|
||||
<e p="Afterburner.cs" t="Include" />
|
||||
<e p="Behaviors.cs" t="Include" />
|
||||
<e p="Cannon.cs" t="Include" />
|
||||
<e p="Launcher.cs" t="Include" />
|
||||
<e p="Reactor.cs" t="Include" />
|
||||
<e p="Sensor.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Assets\Scripts\ServerShared\ItemBehaviors\Afterburner.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ItemBehaviors\Behaviors.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ItemBehaviors\Cannon.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ItemBehaviors\Launcher.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ItemBehaviors\Reactor.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ItemBehaviors\Sensor.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ItemData.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ItemInstance.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\MessagePackObjects" t="Include">
|
||||
<e p="Requests.cs" t="Include" />
|
||||
<e p="Responses.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\JsonConverters.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\MathFormatters.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\MathResolver.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\Messages.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH" t="Include">
|
||||
<e p="JsonKnownTypes" t="Include">
|
||||
<e p="AttributesManager.cs" t="Include" />
|
||||
<e p="Exceptions" t="Include">
|
||||
<e p="JsonKnownTypesException.cs" t="Include" />
|
||||
</e>
|
||||
<e p="JsonDiscriminatorAttribute.cs" t="Include" />
|
||||
<e p="JsonDiscriminatorSettings.cs" t="Include" />
|
||||
<e p="JsonKnownThisTypeAttribute.cs" t="Include" />
|
||||
<e p="JsonKnownTypeAttribute.cs" t="Include" />
|
||||
<e p="JsonKnownTypesContractResolver.cs" t="Include" />
|
||||
<e p="JsonKnownTypesConverter.cs" t="Include" />
|
||||
<e p="JsonKnownTypesDictionaryManager.cs" t="Include" />
|
||||
<e p="JsonKnownTypesSettings.cs" t="Include" />
|
||||
<e p="JsonKnownTypesSettingsManager.cs" t="Include" />
|
||||
<e p="Utils" t="Include">
|
||||
<e p="Mapper.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="LiteNetLib" t="Include">
|
||||
<e p="BaseChannel.cs" t="Include" />
|
||||
<e p="ConnectionRequest.cs" t="Include" />
|
||||
<e p="INetEventListener.cs" t="Include" />
|
||||
<e p="Layers" t="Include">
|
||||
<e p="Crc32cLayer.cs" t="Include" />
|
||||
<e p="PacketLayerBase.cs" t="Include" />
|
||||
<e p="XorEncryptLayer.cs" t="Include" />
|
||||
</e>
|
||||
<e p="NatPunchModule.cs" t="Include" />
|
||||
<e p="NetConstants.cs" t="Include" />
|
||||
<e p="NetDebug.cs" t="Include" />
|
||||
<e p="NetExceptions.cs" t="Include" />
|
||||
<e p="NetManager.cs" t="Include" />
|
||||
<e p="NetPacket.cs" t="Include" />
|
||||
<e p="NetPacketPool.cs" t="Include" />
|
||||
<e p="NetPeer.cs" t="Include" />
|
||||
<e p="NetSocket.cs" t="Include" />
|
||||
<e p="NetStatistics.cs" t="Include" />
|
||||
<e p="NetUtils.cs" t="Include" />
|
||||
<e p="ReliableChannel.cs" t="Include" />
|
||||
<e p="SequencedChannel.cs" t="Include" />
|
||||
<e p="Utils" t="Include">
|
||||
<e p="CRC32C.cs" t="Include" />
|
||||
<e p="FastBitConverter.cs" t="Include" />
|
||||
<e p="INetSerializable.cs" t="Include" />
|
||||
<e p="NetDataReader.cs" t="Include" />
|
||||
<e p="NetDataWriter.cs" t="Include" />
|
||||
<e p="NetPacketProcessor.cs" t="Include" />
|
||||
<e p="NetSerializer.cs" t="Include" />
|
||||
<e p="NtpPacket.cs" t="Include" />
|
||||
<e p="NtpRequest.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="RethinkDb.Driver" t="Include">
|
||||
<e p="Ast" t="Include">
|
||||
<e p="ExtensionHelper.cs" t="Include" />
|
||||
<e p="Poco.cs" t="Include" />
|
||||
<e p="PropertyHelper.cs" t="Include" />
|
||||
<e p="Query.cs" t="Include" />
|
||||
<e p="ReqlAst.cs" t="Include" />
|
||||
<e p="ReqlExpr.cs" t="Include" />
|
||||
<e p="ReqlRaw.cs" t="Include" />
|
||||
<e p="TopLevel.cs" t="Include" />
|
||||
<e p="Util.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ErrorBuilder.cs" t="Include" />
|
||||
<e p="Extras" t="Include">
|
||||
<e p="Dao" t="Include">
|
||||
<e p="Document.cs" t="Include" />
|
||||
<e p="IDao.cs" t="Include" />
|
||||
<e p="RethinkDao.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="Generated" t="Include">
|
||||
<e p="Ast" t="Include">
|
||||
<e p="Add.cs" t="Include" />
|
||||
<e p="And.cs" t="Include" />
|
||||
<e p="Append.cs" t="Include" />
|
||||
<e p="April.cs" t="Include" />
|
||||
<e p="Args.cs" t="Include" />
|
||||
<e p="Asc.cs" t="Include" />
|
||||
<e p="August.cs" t="Include" />
|
||||
<e p="Avg.cs" t="Include" />
|
||||
<e p="Between.cs" t="Include" />
|
||||
<e p="Binary.cs" t="Include" />
|
||||
<e p="Bracket.cs" t="Include" />
|
||||
<e p="Branch.cs" t="Include" />
|
||||
<e p="Ceil.cs" t="Include" />
|
||||
<e p="ChangeAt.cs" t="Include" />
|
||||
<e p="Changes.cs" t="Include" />
|
||||
<e p="Circle.cs" t="Include" />
|
||||
<e p="CoerceTo.cs" t="Include" />
|
||||
<e p="ConcatMap.cs" t="Include" />
|
||||
<e p="Config.cs" t="Include" />
|
||||
<e p="Contains.cs" t="Include" />
|
||||
<e p="Count.cs" t="Include" />
|
||||
<e p="Date.cs" t="Include" />
|
||||
<e p="Datum.cs" t="Include" />
|
||||
<e p="Day.cs" t="Include" />
|
||||
<e p="DayOfWeek.cs" t="Include" />
|
||||
<e p="DayOfYear.cs" t="Include" />
|
||||
<e p="Db.cs" t="Include" />
|
||||
<e p="DbCreate.cs" t="Include" />
|
||||
<e p="DbDrop.cs" t="Include" />
|
||||
<e p="DbList.cs" t="Include" />
|
||||
<e p="December.cs" t="Include" />
|
||||
<e p="Default.cs" t="Include" />
|
||||
<e p="Delete.cs" t="Include" />
|
||||
<e p="DeleteAt.cs" t="Include" />
|
||||
<e p="Desc.cs" t="Include" />
|
||||
<e p="Difference.cs" t="Include" />
|
||||
<e p="Distance.cs" t="Include" />
|
||||
<e p="Distinct.cs" t="Include" />
|
||||
<e p="Div.cs" t="Include" />
|
||||
<e p="Downcase.cs" t="Include" />
|
||||
<e p="During.cs" t="Include" />
|
||||
<e p="EpochTime.cs" t="Include" />
|
||||
<e p="Eq.cs" t="Include" />
|
||||
<e p="EqJoin.cs" t="Include" />
|
||||
<e p="Error.cs" t="Include" />
|
||||
<e p="February.cs" t="Include" />
|
||||
<e p="Fill.cs" t="Include" />
|
||||
<e p="Filter.cs" t="Include" />
|
||||
<e p="Floor.cs" t="Include" />
|
||||
<e p="Fold.cs" t="Include" />
|
||||
<e p="ForEach.cs" t="Include" />
|
||||
<e p="Friday.cs" t="Include" />
|
||||
<e p="Func.cs" t="Include" />
|
||||
<e p="Funcall.cs" t="Include" />
|
||||
<e p="Ge.cs" t="Include" />
|
||||
<e p="Geojson.cs" t="Include" />
|
||||
<e p="Get.cs" t="Include" />
|
||||
<e p="GetAll.cs" t="Include" />
|
||||
<e p="GetField.cs" t="Include" />
|
||||
<e p="GetIntersecting.cs" t="Include" />
|
||||
<e p="GetNearest.cs" t="Include" />
|
||||
<e p="Grant.cs" t="Include" />
|
||||
<e p="Group.cs" t="Include" />
|
||||
<e p="Gt.cs" t="Include" />
|
||||
<e p="HasFields.cs" t="Include" />
|
||||
<e p="Hours.cs" t="Include" />
|
||||
<e p="Http.cs" t="Include" />
|
||||
<e p="Includes.cs" t="Include" />
|
||||
<e p="IndexCreate.cs" t="Include" />
|
||||
<e p="IndexDrop.cs" t="Include" />
|
||||
<e p="IndexList.cs" t="Include" />
|
||||
<e p="IndexRename.cs" t="Include" />
|
||||
<e p="IndexStatus.cs" t="Include" />
|
||||
<e p="IndexWait.cs" t="Include" />
|
||||
<e p="Info.cs" t="Include" />
|
||||
<e p="InnerJoin.cs" t="Include" />
|
||||
<e p="Insert.cs" t="Include" />
|
||||
<e p="InsertAt.cs" t="Include" />
|
||||
<e p="Intersects.cs" t="Include" />
|
||||
<e p="InTimezone.cs" t="Include" />
|
||||
<e p="IsEmpty.cs" t="Include" />
|
||||
<e p="Iso8601.cs" t="Include" />
|
||||
<e p="January.cs" t="Include" />
|
||||
<e p="Javascript.cs" t="Include" />
|
||||
<e p="Json.cs" t="Include" />
|
||||
<e p="July.cs" t="Include" />
|
||||
<e p="June.cs" t="Include" />
|
||||
<e p="Keys.cs" t="Include" />
|
||||
<e p="Le.cs" t="Include" />
|
||||
<e p="Limit.cs" t="Include" />
|
||||
<e p="Line.cs" t="Include" />
|
||||
<e p="Literal.cs" t="Include" />
|
||||
<e p="Lt.cs" t="Include" />
|
||||
<e p="MakeArray.cs" t="Include" />
|
||||
<e p="MakeObj.cs" t="Include" />
|
||||
<e p="Map.cs" t="Include" />
|
||||
<e p="March.cs" t="Include" />
|
||||
<e p="Match.cs" t="Include" />
|
||||
<e p="Max.cs" t="Include" />
|
||||
<e p="Maxval.cs" t="Include" />
|
||||
<e p="May.cs" t="Include" />
|
||||
<e p="Merge.cs" t="Include" />
|
||||
<e p="Min.cs" t="Include" />
|
||||
<e p="Minutes.cs" t="Include" />
|
||||
<e p="Minval.cs" t="Include" />
|
||||
<e p="Mod.cs" t="Include" />
|
||||
<e p="Monday.cs" t="Include" />
|
||||
<e p="Month.cs" t="Include" />
|
||||
<e p="Mul.cs" t="Include" />
|
||||
<e p="Ne.cs" t="Include" />
|
||||
<e p="Not.cs" t="Include" />
|
||||
<e p="November.cs" t="Include" />
|
||||
<e p="Now.cs" t="Include" />
|
||||
<e p="Nth.cs" t="Include" />
|
||||
<e p="October.cs" t="Include" />
|
||||
<e p="OffsetsOf.cs" t="Include" />
|
||||
<e p="Or.cs" t="Include" />
|
||||
<e p="OrderBy.cs" t="Include" />
|
||||
<e p="OuterJoin.cs" t="Include" />
|
||||
<e p="Pluck.cs" t="Include" />
|
||||
<e p="Point.cs" t="Include" />
|
||||
<e p="Polygon.cs" t="Include" />
|
||||
<e p="PolygonSub.cs" t="Include" />
|
||||
<e p="Prepend.cs" t="Include" />
|
||||
<e p="random.cs" t="Include" />
|
||||
<e p="Range.cs" t="Include" />
|
||||
<e p="Rebalance.cs" t="Include" />
|
||||
<e p="Reconfigure.cs" t="Include" />
|
||||
<e p="Reduce.cs" t="Include" />
|
||||
<e p="Replace.cs" t="Include" />
|
||||
<e p="ReqlExpr.cs" t="Include" />
|
||||
<e p="ReqlObject.cs" t="Include" />
|
||||
<e p="Round.cs" t="Include" />
|
||||
<e p="Sample.cs" t="Include" />
|
||||
<e p="Saturday.cs" t="Include" />
|
||||
<e p="Seconds.cs" t="Include" />
|
||||
<e p="September.cs" t="Include" />
|
||||
<e p="SetDifference.cs" t="Include" />
|
||||
<e p="SetInsert.cs" t="Include" />
|
||||
<e p="SetIntersection.cs" t="Include" />
|
||||
<e p="SetUnion.cs" t="Include" />
|
||||
<e p="Skip.cs" t="Include" />
|
||||
<e p="Slice.cs" t="Include" />
|
||||
<e p="SpliceAt.cs" t="Include" />
|
||||
<e p="Split.cs" t="Include" />
|
||||
<e p="Status.cs" t="Include" />
|
||||
<e p="Sub.cs" t="Include" />
|
||||
<e p="Sum.cs" t="Include" />
|
||||
<e p="Sunday.cs" t="Include" />
|
||||
<e p="Sync.cs" t="Include" />
|
||||
<e p="Table.cs" t="Include" />
|
||||
<e p="TableCreate.cs" t="Include" />
|
||||
<e p="TableDrop.cs" t="Include" />
|
||||
<e p="TableList.cs" t="Include" />
|
||||
<e p="Thursday.cs" t="Include" />
|
||||
<e p="Time.cs" t="Include" />
|
||||
<e p="TimeOfDay.cs" t="Include" />
|
||||
<e p="Timezone.cs" t="Include" />
|
||||
<e p="ToEpochTime.cs" t="Include" />
|
||||
<e p="ToGeojson.cs" t="Include" />
|
||||
<e p="ToIso8601.cs" t="Include" />
|
||||
<e p="ToJsonString.cs" t="Include" />
|
||||
<e p="Tuesday.cs" t="Include" />
|
||||
<e p="TypeOf.cs" t="Include" />
|
||||
<e p="Ungroup.cs" t="Include" />
|
||||
<e p="Union.cs" t="Include" />
|
||||
<e p="Upcase.cs" t="Include" />
|
||||
<e p="Update.cs" t="Include" />
|
||||
<e p="Uuid.cs" t="Include" />
|
||||
<e p="Values.cs" t="Include" />
|
||||
<e p="Var.cs" t="Include" />
|
||||
<e p="Wait.cs" t="Include" />
|
||||
<e p="Wednesday.cs" t="Include" />
|
||||
<e p="WithFields.cs" t="Include" />
|
||||
<e p="Without.cs" t="Include" />
|
||||
<e p="Year.cs" t="Include" />
|
||||
<e p="Zip.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Model" t="Include">
|
||||
<e p="AuthType.cs" t="Include" />
|
||||
<e p="Bound.cs" t="Include" />
|
||||
<e p="Conflict.cs" t="Include" />
|
||||
<e p="Durability.cs" t="Include" />
|
||||
<e p="EmergencyRepair.cs" t="Include" />
|
||||
<e p="Format.cs" t="Include" />
|
||||
<e p="GeoSystem.cs" t="Include" />
|
||||
<e p="HttpMethod.cs" t="Include" />
|
||||
<e p="IdentifierFormat.cs" t="Include" />
|
||||
<e p="ReadMode.cs" t="Include" />
|
||||
<e p="ReqlFunction0.cs" t="Include" />
|
||||
<e p="ReqlFunction1.cs" t="Include" />
|
||||
<e p="ReqlFunction2.cs" t="Include" />
|
||||
<e p="ReqlFunction3.cs" t="Include" />
|
||||
<e p="ReqlFunction4.cs" t="Include" />
|
||||
<e p="ResultFormat.cs" t="Include" />
|
||||
<e p="Status.cs" t="Include" />
|
||||
<e p="TopLevel.cs" t="Include" />
|
||||
<e p="Unit.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Proto" t="Include">
|
||||
<e p="DatumType.cs" t="Include" />
|
||||
<e p="ErrorType.cs" t="Include" />
|
||||
<e p="FrameType.cs" t="Include" />
|
||||
<e p="Protocol.cs" t="Include" />
|
||||
<e p="QueryType.cs" t="Include" />
|
||||
<e p="ResponseNote.cs" t="Include" />
|
||||
<e p="ResponseType.cs" t="Include" />
|
||||
<e p="TermType.cs" t="Include" />
|
||||
<e p="Version.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ReqlAuthError.cs" t="Include" />
|
||||
<e p="ReqlAvailabilityError.cs" t="Include" />
|
||||
<e p="ReqlClientError.cs" t="Include" />
|
||||
<e p="ReqlCompileError.cs" t="Include" />
|
||||
<e p="ReqlDriverCompileError.cs" t="Include" />
|
||||
<e p="ReqlDriverError.cs" t="Include" />
|
||||
<e p="ReqlError.cs" t="Include" />
|
||||
<e p="ReqlInternalError.cs" t="Include" />
|
||||
<e p="ReqlNonExistenceError.cs" t="Include" />
|
||||
<e p="ReqlOpFailedError.cs" t="Include" />
|
||||
<e p="ReqlOpIndeterminateError.cs" t="Include" />
|
||||
<e p="ReqlPermissionError.cs" t="Include" />
|
||||
<e p="ReqlQueryLogicError.cs" t="Include" />
|
||||
<e p="ReqlResourceLimitError.cs" t="Include" />
|
||||
<e p="ReqlRuntimeError.cs" t="Include" />
|
||||
<e p="ReqlServerCompileError.cs" t="Include" />
|
||||
<e p="ReqlUserError.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Log.cs" t="Include" />
|
||||
<e p="Model" t="Include">
|
||||
<e p="Arguments.cs" t="Include" />
|
||||
<e p="Backtrace.cs" t="Include" />
|
||||
<e p="Change[T].cs" t="Include" />
|
||||
<e p="ExtensionsForResult.cs" t="Include" />
|
||||
<e p="GroupedResult.cs" t="Include" />
|
||||
<e p="MapObject.cs" t="Include" />
|
||||
<e p="OptArgs.cs" t="Include" />
|
||||
<e p="PathSpec.cs" t="Include" />
|
||||
<e p="Profile.cs" t="Include" />
|
||||
<e p="ReqlLambda.cs" t="Include" />
|
||||
<e p="Result.cs" t="Include" />
|
||||
<e p="Server.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Net" t="Include">
|
||||
<e p="Awaiter.cs" t="Include" />
|
||||
<e p="Clustering" t="Include">
|
||||
<e p="ConnectionPool.cs" t="Include" />
|
||||
<e p="EpsilonGreedy.cs" t="Include" />
|
||||
<e p="EpsilonValueCalculator.cs" t="Include" />
|
||||
<e p="ExceptionIs.cs" t="Include" />
|
||||
<e p="HostEntry.cs" t="Include" />
|
||||
<e p="HostPool.cs" t="Include" />
|
||||
<e p="IPoolingStrategy.cs" t="Include" />
|
||||
<e p="RoundRobinHostPool.cs" t="Include" />
|
||||
<e p="Seed.cs" t="Include" />
|
||||
<e p="Server.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Connection.cs" t="Include" />
|
||||
<e p="Converter.cs" t="Include" />
|
||||
<e p="Crypto.cs" t="Include" />
|
||||
<e p="Cursor.cs" t="Include" />
|
||||
<e p="FormatOptions.cs" t="Include" />
|
||||
<e p="Handshake.cs" t="Include" />
|
||||
<e p="IConnection.cs" t="Include" />
|
||||
<e p="IConnectionBuilder.cs" t="Include" />
|
||||
<e p="ICursor.cs" t="Include" />
|
||||
<e p="IncrementalSHA256.cs" t="Include" />
|
||||
<e p="JsonConverters" t="Include">
|
||||
<e p="ExtensionsForJsonConverters.cs" t="Include" />
|
||||
<e p="ReqlBinaryConverter.cs" t="Include" />
|
||||
<e p="ReqlDateTimeConverter.cs" t="Include" />
|
||||
<e p="ReqlExprConverter.cs" t="Include" />
|
||||
<e p="ReqlGroupingConverter.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Response.cs" t="Include" />
|
||||
<e p="ScramAttributes.cs" t="Include" />
|
||||
<e p="SecureRandom.cs" t="Include" />
|
||||
<e p="SocketWrapper.cs" t="Include" />
|
||||
<e p="SslContext.cs" t="Include" />
|
||||
</e>
|
||||
<e p="ReqlAssertFailure.cs" t="Include" />
|
||||
<e p="RethinkDB.cs" t="Include" />
|
||||
<e p="RethinkDBConstants.cs" t="Include" />
|
||||
<e p="Utils" t="Include">
|
||||
<e p="CancellableTask.cs" t="Include" />
|
||||
<e p="ExtensionsForEvent.cs" t="Include" />
|
||||
<e p="ExtensionsForString.cs" t="Include" />
|
||||
<e p="ExtensionsForTcpClient.cs" t="Include" />
|
||||
<e p="ExtensionsForType.cs" t="Include" />
|
||||
<e p="QueryHelper.cs" t="Include" />
|
||||
<e p="StringHelper.cs" t="Include" />
|
||||
<e p="TaskHelper.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="RethinkDb.Driver.Linq" t="Include">
|
||||
<e p="Attributes" t="Include">
|
||||
<e p="PrimaryIndexAttribute.cs" t="Include" />
|
||||
<e p="SecondaryIndexAttribute.cs" t="Include" />
|
||||
</e>
|
||||
<e p="LinqExtensions.cs" t="Include" />
|
||||
<e p="MemberNameResolver.cs" t="Include" />
|
||||
<e p="RethinkDbGroup.cs" t="Include" />
|
||||
<e p="RethinkDbQueryModelVisitor.cs" t="Include" />
|
||||
<e p="RethinkQueryable.cs" t="Include" />
|
||||
<e p="RethinkQueryExecutor.cs" t="Include" />
|
||||
<e p="SelectionProjector.cs" t="Include" />
|
||||
<e p="WhereClauseParsers" t="Include">
|
||||
<e p="BaseIndexParser.cs" t="Include" />
|
||||
<e p="DefaultParser.cs" t="Include" />
|
||||
<e p="ExpressionVisitor.cs" t="Include" />
|
||||
<e p="ExprHelper.cs" t="Include" />
|
||||
<e p="GroupItemsParser.cs" t="Include" />
|
||||
<e p="IWhereClauseParser.cs" t="Include" />
|
||||
<e p="PrimaryIndexParser.cs" t="Include" />
|
||||
<e p="SecondaryIndexParser.cs" t="Include" />
|
||||
<e p="SubQueryVisitor" t="Include">
|
||||
<e p="AllSubQueryVisitor.cs" t="Include" />
|
||||
<e p="AnySubQueryVisitor.cs" t="Include" />
|
||||
<e p="BaseFilterableSubQueryVisitor.cs" t="Include" />
|
||||
<e p="BaseSubQueryVisitor.cs" t="Include" />
|
||||
<e p="ContainsSubQueryVisitor.cs" t="Include" />
|
||||
<e p="CountSubQueryVisitor.cs" t="Include" />
|
||||
<e p="FirstSubQueryVisitor.cs" t="Include" />
|
||||
<e p="ISubQueryVisitor.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
</e>
|
||||
</e>
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\AttributesManager.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\Exceptions\JsonKnownTypesException.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonDiscriminatorAttribute.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonDiscriminatorSettings.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonKnownThisTypeAttribute.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonKnownTypeAttribute.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonKnownTypesContractResolver.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonKnownTypesConverter.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonKnownTypesDictionaryManager.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonKnownTypesSettings.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\JsonKnownTypesSettingsManager.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\NIH\JsonKnownTypes\Utils\Mapper.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\OrbitInstance.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\Services" t="Include">
|
||||
<e p="IChatService.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Assets\Scripts\ServerShared\Ship.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ZoneData.cs" t="Include" />
|
||||
<e p="Assets\Scripts\ServerShared\ZoneGenerator.cs" t="Include" />
|
||||
<e p="Economy.Server" t="IncludeRecursive">
|
||||
<e p="appsettings.json" t="Include" />
|
||||
<e p="bin" t="ExcludeRecursive" />
|
||||
<e p="ChatHub.cs" t="Include" />
|
||||
<e p="ChatService.cs" t="Include" />
|
||||
<e p="Economy.Server.csproj" t="IncludeRecursive" />
|
||||
<e p="obj" t="ExcludeRecursive">
|
||||
<e p="Debug" t="Include">
|
||||
|
|
@ -60,6 +445,7 @@
|
|||
</e>
|
||||
</e>
|
||||
<e p="Program.cs" t="Include" />
|
||||
<e p="Server.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Economy.Shared" t="IncludeRecursive">
|
||||
<e p="bin" t="ExcludeRecursive" />
|
||||
|
|
|
|||
|
|
@ -6,12 +6,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Economy.Shared.Unity", "Eco
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessagePack", "MessagePack.csproj", "{21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagicOnion", "MagicOnion.csproj", "{8646472B-6F4E-DCCA-A987-99E48366FF7F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagicOnion.Abstractions", "MagicOnion.Abstractions.csproj", "{7A90811F-E771-FAB4-C8B5-EA6DF36C4D19}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagicOnion.Unity", "MagicOnion.Unity.csproj", "{B83AC090-25E2-7BA3-4612-A18BBB80B3E6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Assembly-CSharp-firstpass", "Assembly-CSharp-firstpass.csproj", "{7D8742A4-0DFC-5667-0A98-3CA4312F9253}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Assembly-CSharp-Editor", "Assembly-CSharp-Editor.csproj", "{E389FCA7-CA14-82FB-7D67-C13788BEE74A}"
|
||||
|
|
@ -34,18 +28,6 @@ Global
|
|||
{21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8646472B-6F4E-DCCA-A987-99E48366FF7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8646472B-6F4E-DCCA-A987-99E48366FF7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8646472B-6F4E-DCCA-A987-99E48366FF7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8646472B-6F4E-DCCA-A987-99E48366FF7F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7A90811F-E771-FAB4-C8B5-EA6DF36C4D19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7A90811F-E771-FAB4-C8B5-EA6DF36C4D19}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7A90811F-E771-FAB4-C8B5-EA6DF36C4D19}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7A90811F-E771-FAB4-C8B5-EA6DF36C4D19}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B83AC090-25E2-7BA3-4612-A18BBB80B3E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B83AC090-25E2-7BA3-4612-A18BBB80B3E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B83AC090-25E2-7BA3-4612-A18BBB80B3E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B83AC090-25E2-7BA3-4612-A18BBB80B3E6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7D8742A4-0DFC-5667-0A98-3CA4312F9253}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7D8742A4-0DFC-5667-0A98-3CA4312F9253}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7D8742A4-0DFC-5667-0A98-3CA4312F9253}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
|
|||
|
|
@ -401,12 +401,6 @@
|
|||
<Reference Include="Grpc.Core.Api">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RethinkDb.Driver">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/RethinkDb.Driver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RethinkDb.Driver.Linq">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/RethinkDb.Driver.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
|
|
@ -784,18 +778,6 @@
|
|||
<Project>{A62B36C2-E9DE-B992-0779-F5FCF5968986}</Project>
|
||||
<Name>Economy.Shared.Unity</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.csproj">
|
||||
<Project>{8646472B-6F4E-DCCA-A987-99E48366FF7F}</Project>
|
||||
<Name>MagicOnion</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.Unity.csproj">
|
||||
<Project>{B83AC090-25E2-7BA3-4612-A18BBB80B3E6}</Project>
|
||||
<Name>MagicOnion.Unity</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.Abstractions.csproj">
|
||||
<Project>{7A90811F-E771-FAB4-C8B5-EA6DF36C4D19}</Project>
|
||||
<Name>MagicOnion.Abstractions</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MessagePack.csproj">
|
||||
<Project>{21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}</Project>
|
||||
<Name>MessagePack</Name>
|
||||
|
|
|
|||
|
|
@ -312,12 +312,6 @@
|
|||
<Reference Include="Grpc.Core.Api">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RethinkDb.Driver">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/RethinkDb.Driver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RethinkDb.Driver.Linq">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/RethinkDb.Driver.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
|
|
@ -687,18 +681,6 @@
|
|||
<Project>{A62B36C2-E9DE-B992-0779-F5FCF5968986}</Project>
|
||||
<Name>Economy.Shared.Unity</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.csproj">
|
||||
<Project>{8646472B-6F4E-DCCA-A987-99E48366FF7F}</Project>
|
||||
<Name>MagicOnion</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.Unity.csproj">
|
||||
<Project>{B83AC090-25E2-7BA3-4612-A18BBB80B3E6}</Project>
|
||||
<Name>MagicOnion.Unity</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.Abstractions.csproj">
|
||||
<Project>{7A90811F-E771-FAB4-C8B5-EA6DF36C4D19}</Project>
|
||||
<Name>MagicOnion.Abstractions</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MessagePack.csproj">
|
||||
<Project>{21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}</Project>
|
||||
<Name>MessagePack</Name>
|
||||
|
|
|
|||
|
|
@ -60,10 +60,8 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Assets\Scripts\ChatComponent.cs" />
|
||||
<Compile Include="Assets\Scripts\CultClient.cs" />
|
||||
<Compile Include="Assets\Scripts\Galaxy.cs" />
|
||||
<Compile Include="Assets\Scripts\Generated\MagicOnion.Generated.cs" />
|
||||
<Compile Include="Assets\Scripts\Generated\MessagePack.Generated.cs" />
|
||||
<Compile Include="Assets\Scripts\Icons.cs" />
|
||||
<Compile Include="Assets\Scripts\InitialSettings.cs" />
|
||||
<Compile Include="Assets\Scripts\MarkovNameGenerator.cs" />
|
||||
|
|
@ -647,12 +645,6 @@
|
|||
<Reference Include="Grpc.Core.Api">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RethinkDb.Driver">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/RethinkDb.Driver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RethinkDb.Driver.Linq">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/RethinkDb.Driver.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>C:/Users/rwvens/Documents/GitHub/Aetheria-Economy/Assets/Plugins/Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
|
|
@ -1026,18 +1018,6 @@
|
|||
<Project>{A62B36C2-E9DE-B992-0779-F5FCF5968986}</Project>
|
||||
<Name>Economy.Shared.Unity</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.csproj">
|
||||
<Project>{8646472B-6F4E-DCCA-A987-99E48366FF7F}</Project>
|
||||
<Name>MagicOnion</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.Unity.csproj">
|
||||
<Project>{B83AC090-25E2-7BA3-4612-A18BBB80B3E6}</Project>
|
||||
<Name>MagicOnion.Unity</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MagicOnion.Abstractions.csproj">
|
||||
<Project>{7A90811F-E771-FAB4-C8B5-EA6DF36C4D19}</Project>
|
||||
<Name>MagicOnion.Abstractions</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="MessagePack.csproj">
|
||||
<Project>{21EF11C5-27DC-3D88-B027-9A4B6F36BAE4}</Project>
|
||||
<Name>MessagePack</Name>
|
||||
|
|
|
|||
BIN
Assets/Plugins/RethinkDb.Driver.Linq.dll
(Stored with Git LFS)
BIN
Assets/Plugins/RethinkDb.Driver.Linq.dll
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,100 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a4834ab237984c34989bbc2898518295
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 0
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Editor: 0
|
||||
Exclude Linux: 0
|
||||
Exclude Linux64: 0
|
||||
Exclude LinuxUniversal: 0
|
||||
Exclude OSXUniversal: 0
|
||||
Exclude WebGL: 0
|
||||
Exclude Win: 0
|
||||
Exclude Win64: 0
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/RethinkDb.Driver.dll
(Stored with Git LFS)
BIN
Assets/Plugins/RethinkDb.Driver.dll
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,100 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 800dfc6b8095d9f48975a03adc1d51fb
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 0
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Editor: 0
|
||||
Exclude Linux: 0
|
||||
Exclude Linux64: 0
|
||||
Exclude LinuxUniversal: 0
|
||||
Exclude OSXUniversal: 0
|
||||
Exclude WebGL: 0
|
||||
Exclude Win: 0
|
||||
Exclude Win64: 0
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,223 +0,0 @@
|
|||
using ChatApp.Shared.Hubs;
|
||||
using ChatApp.Shared.MessagePackObjects;
|
||||
using ChatApp.Shared.Services;
|
||||
using Grpc.Core;
|
||||
using MagicOnion.Client;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Assets.Scripts
|
||||
{
|
||||
public class ChatComponent : MonoBehaviour, IChatHubReceiver
|
||||
{
|
||||
private Channel channel;
|
||||
private IChatHub streamingClient;
|
||||
private IChatService client;
|
||||
|
||||
private bool isJoin;
|
||||
private bool isSelfDisConnected;
|
||||
|
||||
public Text ChatText;
|
||||
|
||||
public Button JoinOrLeaveButton;
|
||||
|
||||
public Text JoinOrLeaveButtonText;
|
||||
|
||||
public Button SendMessageButton;
|
||||
|
||||
public InputField Input;
|
||||
|
||||
public InputField ReportInput;
|
||||
|
||||
public Button SendReportButton;
|
||||
|
||||
public Button DisconnectButon;
|
||||
public Button ExceptionButton;
|
||||
public Button UnaryExceptionButton;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
this.InitializeClient();
|
||||
this.InitializeUi();
|
||||
}
|
||||
|
||||
|
||||
async void OnDestroy()
|
||||
{
|
||||
// Clean up Hub and channel
|
||||
await this.streamingClient.DisposeAsync();
|
||||
await this.channel.ShutdownAsync();
|
||||
}
|
||||
|
||||
|
||||
private void InitializeClient()
|
||||
{
|
||||
// Initialize the Hub
|
||||
this.channel = new Channel("localhost", 12345, ChannelCredentials.Insecure);
|
||||
// for SSL/TLS connection
|
||||
//var serverCred = new SslCredentials(File.ReadAllText(Path.Combine(Application.streamingAssetsPath, "server.crt")));
|
||||
//this.channel = new Channel("test.example.com", 12345, serverCred);
|
||||
this.streamingClient = StreamingHubClient.Connect<IChatHub, IChatHubReceiver>(this.channel, this);
|
||||
this.RegisterDisconnectEvent(streamingClient);
|
||||
this.client = MagicOnionClient.Create<IChatService>(this.channel);
|
||||
}
|
||||
|
||||
|
||||
private void InitializeUi()
|
||||
{
|
||||
this.isJoin = false;
|
||||
|
||||
this.SendMessageButton.interactable = false;
|
||||
this.ChatText.text = string.Empty;
|
||||
this.Input.text = string.Empty;
|
||||
this.Input.placeholder.GetComponent<Text>().text = "Please enter your name.";
|
||||
this.JoinOrLeaveButtonText.text = "Enter the room";
|
||||
this.ExceptionButton.interactable = false;
|
||||
}
|
||||
|
||||
|
||||
private async void RegisterDisconnectEvent(IChatHub streamingClient)
|
||||
{
|
||||
try
|
||||
{
|
||||
// you can wait disconnected event
|
||||
await streamingClient.WaitForDisconnect();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// try-to-reconnect? logging event? close? etc...
|
||||
Debug.Log("disconnected server.");
|
||||
|
||||
if (this.isSelfDisConnected)
|
||||
{
|
||||
// there is no particular meaning
|
||||
await Task.Delay(2000);
|
||||
|
||||
// reconnect
|
||||
this.ReconnectServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async void DisconnectServer()
|
||||
{
|
||||
this.isSelfDisConnected = true;
|
||||
|
||||
this.JoinOrLeaveButton.interactable = false;
|
||||
this.SendMessageButton.interactable = false;
|
||||
this.SendReportButton.interactable = false;
|
||||
this.DisconnectButon.interactable = false;
|
||||
this.ExceptionButton.interactable = false;
|
||||
this.UnaryExceptionButton.interactable = false;
|
||||
|
||||
if (this.isJoin)
|
||||
this.JoinOrLeave();
|
||||
|
||||
await this.streamingClient.DisposeAsync();
|
||||
}
|
||||
|
||||
|
||||
private void ReconnectServer()
|
||||
{
|
||||
this.streamingClient = StreamingHubClient.Connect<IChatHub, IChatHubReceiver>(this.channel, this);
|
||||
this.RegisterDisconnectEvent(streamingClient);
|
||||
Debug.Log("Reconnected server.");
|
||||
|
||||
this.JoinOrLeaveButton.interactable = true;
|
||||
this.SendMessageButton.interactable = false;
|
||||
this.SendReportButton.interactable = true;
|
||||
this.DisconnectButon.interactable = true;
|
||||
this.ExceptionButton.interactable = true;
|
||||
this.UnaryExceptionButton.interactable = true;
|
||||
|
||||
this.isSelfDisConnected = false;
|
||||
}
|
||||
|
||||
|
||||
#region Client -> Server (Streaming)
|
||||
public async void JoinOrLeave()
|
||||
{
|
||||
if (this.isJoin)
|
||||
{
|
||||
await this.streamingClient.LeaveAsync();
|
||||
|
||||
this.InitializeUi();
|
||||
}
|
||||
else
|
||||
{
|
||||
var request = new JoinRequest { RoomName = "SampleRoom", UserName = this.Input.text };
|
||||
await this.streamingClient.JoinAsync(request);
|
||||
|
||||
this.isJoin = true;
|
||||
this.SendMessageButton.interactable = true;
|
||||
this.JoinOrLeaveButtonText.text = "Leave the room";
|
||||
this.Input.text = string.Empty;
|
||||
this.Input.placeholder.GetComponent<Text>().text = "Please enter a comment.";
|
||||
this.ExceptionButton.interactable = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async void SendMessage()
|
||||
{
|
||||
if (!this.isJoin)
|
||||
return;
|
||||
|
||||
await this.streamingClient.SendMessageAsync(this.Input.text);
|
||||
|
||||
this.Input.text = string.Empty;
|
||||
}
|
||||
|
||||
public async void GenerateException()
|
||||
{
|
||||
// hub
|
||||
if (!this.isJoin) return;
|
||||
await this.streamingClient.GenerateException("client exception(streaminghub)!");
|
||||
}
|
||||
|
||||
public void SampleMethod()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Server -> Client (Streaming)
|
||||
public void OnJoin(string name)
|
||||
{
|
||||
this.ChatText.text += $"\n<color=grey>{name} entered the room.</color>";
|
||||
}
|
||||
|
||||
|
||||
public void OnLeave(string name)
|
||||
{
|
||||
this.ChatText.text += $"\n<color=grey>{name} left the room.</color>";
|
||||
}
|
||||
|
||||
public void OnSendMessage(MessageResponse message)
|
||||
{
|
||||
this.ChatText.text += $"\n{message.UserName}:{message.Message}";
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Client -> Server (Unary)
|
||||
public async void SendReport()
|
||||
{
|
||||
await this.client.SendReportAsync(this.ReportInput.text);
|
||||
|
||||
this.ReportInput.text = string.Empty;
|
||||
}
|
||||
|
||||
public async void UnaryGenerateException()
|
||||
{
|
||||
// unary
|
||||
await this.client.GenerateException("client exception(unary)!");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
69
Assets/Scripts/CultClient.cs
Normal file
69
Assets/Scripts/CultClient.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using LiteNetLib;
|
||||
using MessagePack;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
|
||||
public static class CultClient {
|
||||
public static Action<string> Logger = s =>
|
||||
MainThreadDispatcher.Post(_=>Debug.Log(s),null);
|
||||
|
||||
public static NetManager Client;
|
||||
private static NetPeer _peer;
|
||||
private static Dictionary<Type, NotAnActionCollection> _messageCallbacks = new Dictionary<Type, NotAnActionCollection>();
|
||||
|
||||
public static void Send<T>(T m) where T : Message
|
||||
{
|
||||
Logger($"Sending message {MessagePackSerializer.SerializeToJson(m as Message)}");
|
||||
_peer.Send(m as Message);
|
||||
}
|
||||
|
||||
public static void ClearMessageListeners()
|
||||
{
|
||||
_messageCallbacks.Clear();
|
||||
}
|
||||
|
||||
public static void AddMessageListener<T>(Action<T> callback) where T : Message
|
||||
{
|
||||
if (!_messageCallbacks.ContainsKey(typeof(T)))
|
||||
_messageCallbacks[typeof(T)] = new ActionCollection<T>();
|
||||
((ActionCollection<T>)_messageCallbacks[typeof(T)]).Add(callback);
|
||||
}
|
||||
|
||||
public static void Connect(string host = "localhost", int port = 3075)
|
||||
{
|
||||
EventBasedNetListener listener = new EventBasedNetListener();
|
||||
Client = new NetManager(listener)
|
||||
{
|
||||
// UnsyncedEvents = true,
|
||||
// MergeEnabled = true,
|
||||
// NatPunchEnabled = true
|
||||
};
|
||||
Client.Start(3074);
|
||||
_peer = Client.Connect(host, port, "aetheria-cc65a44d");
|
||||
Observable.EveryUpdate().Subscribe(_ => Client.PollEvents());
|
||||
listener.NetworkErrorEvent += (point, code) => Logger($"{point.Address}: Error {code}");
|
||||
listener.NetworkReceiveEvent += (peer, reader, method) =>
|
||||
{
|
||||
Logger($"Received message: {MessagePackSerializer.ConvertToJson(new ReadOnlyMemory<byte>(reader.RawData))}");
|
||||
var message = MessagePackSerializer.Deserialize<Message>(reader.RawData);
|
||||
var type = message.GetType();
|
||||
if (_messageCallbacks.ContainsKey(type))
|
||||
typeof(ActionCollection<>).MakeGenericType(new[] {type}).GetMethod("Invoke").Invoke(_messageCallbacks[type], new object[] {message});
|
||||
};
|
||||
listener.PeerConnectedEvent += peer =>
|
||||
{
|
||||
Logger($"Peer {peer.EndPoint.Address}:{peer.EndPoint.Port} connected.");
|
||||
_peer = peer;
|
||||
// onConnect();
|
||||
};
|
||||
listener.PeerDisconnectedEvent += (peer, info) =>
|
||||
{
|
||||
Logger($"Peer {peer.EndPoint.Address}:{peer.EndPoint.Port} disconnected: {info.Reason}.");
|
||||
_peer = null;
|
||||
};
|
||||
// listener.NetworkLatencyUpdateEvent += (peer, latency) => Logger($"Ping received: {latency} ms");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d1954ea03abc7c34fba72fdd2cd9a8bf
|
||||
guid: 7e7103131b037e44095bb2e8a7c0b28a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using RethinkDb.Driver;
|
||||
using RethinkDb.Driver.Net;
|
||||
using UniRx;
|
||||
|
|
@ -79,7 +80,18 @@ public class DatabaseListView : EditorWindow
|
|||
void OnEnable()
|
||||
{
|
||||
// Add Unity.Mathematics serialization support to RethinkDB Driver
|
||||
Converter.Serializer.Converters.Add(new MathJsonConverter());
|
||||
//Converter.Serializer.Converters.Add(new MathJsonConverter());
|
||||
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
|
||||
{
|
||||
Converters = new List<JsonConverter>
|
||||
{
|
||||
new MathJsonConverter(),
|
||||
Converter.DateTimeConverter,
|
||||
Converter.BinaryConverter,
|
||||
Converter.GroupingConverter,
|
||||
Converter.PocoExprConverter
|
||||
}
|
||||
};
|
||||
|
||||
// Create database cache
|
||||
_databaseCache = new DatabaseCache();
|
||||
|
|
@ -144,16 +156,22 @@ public class DatabaseListView : EditorWindow
|
|||
Debug.Log("Connected to RethinkDB");
|
||||
|
||||
// When entries are changed locally, push the changes to RethinkDB
|
||||
_databaseCache.OnDataUpdateLocal += entry =>
|
||||
_databaseCache.OnDataUpdateLocal += async entry =>
|
||||
{
|
||||
Debug.Log($"Uploading entry to RethinkDB: {entry.ID}");
|
||||
R.Db("Aetheria").Table("Items").Replace(entry).RunAsync(_connection);
|
||||
var result = await R.Db("Aetheria").Table("Items").Update(entry).RunAsync(_connection);
|
||||
Debug.Log($"Uploaded entry to RethinkDB: {entry.ID} result: {result}");
|
||||
};
|
||||
|
||||
_databaseCache.OnDataInsertLocal += async entry =>
|
||||
{
|
||||
var result = await R.Db("Aetheria").Table("Items").Insert(entry).RunAsync(_connection);
|
||||
Debug.Log($"Inserted entry to RethinkDB: {entry.ID} result: {result}");
|
||||
};
|
||||
|
||||
_databaseCache.OnDataDeleteLocal += entry =>
|
||||
_databaseCache.OnDataDeleteLocal += async entry =>
|
||||
{
|
||||
Debug.Log($"Deleting entry from RethinkDB: {entry.ID}");
|
||||
R.Db("Aetheria").Table("Items").Get(entry).Delete().RunAsync(_connection);
|
||||
var result = await R.Db("Aetheria").Table("Items").Get(entry.ID).Delete().RunAsync(_connection);
|
||||
Debug.Log($"Deleted entry from RethinkDB: {entry.ID} result: {result}");
|
||||
};
|
||||
|
||||
// Get all item data from RethinkDB
|
||||
|
|
@ -176,9 +194,13 @@ public class DatabaseListView : EditorWindow
|
|||
while (await result.MoveNextAsync())
|
||||
{
|
||||
var change = result.Current;
|
||||
var entry = change.NewValue;
|
||||
Debug.Log($"Received change to entry from RethinkDB: {entry.ID}");
|
||||
_databaseCache.Add(entry, true);
|
||||
if(change.OldValue == null)
|
||||
Debug.Log($"Received change from RethinkDB (Entry Created): {change.NewValue.ID}");
|
||||
else if(change.NewValue == null)
|
||||
Debug.Log($"Received change from RethinkDB (Entry Deleted): {change.OldValue.ID}");
|
||||
else
|
||||
Debug.Log($"Received change from RethinkDB: {change.NewValue.ID}");
|
||||
_databaseCache.Add(change.NewValue, true);
|
||||
}
|
||||
}).WrapErrors();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,397 +0,0 @@
|
|||
// <auto-generated />
|
||||
#pragma warning disable 618
|
||||
#pragma warning disable 612
|
||||
#pragma warning disable 414
|
||||
#pragma warning disable 219
|
||||
#pragma warning disable 168
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Linq;
|
||||
using global::MagicOnion;
|
||||
using global::MagicOnion.Client;
|
||||
|
||||
public static partial class MagicOnionInitializer
|
||||
{
|
||||
static bool isRegistered = false;
|
||||
|
||||
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
public static void Register()
|
||||
{
|
||||
if(isRegistered) return;
|
||||
isRegistered = true;
|
||||
|
||||
MagicOnionClientRegistry<ChatApp.Shared.Services.IChatService>.Register((x, y, z) => new ChatApp.Shared.Services.ChatServiceClient(x, y, z));
|
||||
|
||||
StreamingHubClientRegistry<ChatApp.Shared.Hubs.IChatHub, ChatApp.Shared.Hubs.IChatHubReceiver>.Register((a, _, b, c, d, e) => new ChatApp.Shared.Hubs.ChatHubClient(a, b, c, d, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 168
|
||||
#pragma warning restore 219
|
||||
#pragma warning restore 414
|
||||
#pragma warning restore 612
|
||||
#pragma warning restore 618
|
||||
#pragma warning disable 618
|
||||
#pragma warning disable 612
|
||||
#pragma warning disable 414
|
||||
#pragma warning disable 219
|
||||
#pragma warning disable 168
|
||||
|
||||
namespace MagicOnion.Resolvers
|
||||
{
|
||||
using System;
|
||||
using MessagePack;
|
||||
|
||||
public class MagicOnionResolver : global::MessagePack.IFormatterResolver
|
||||
{
|
||||
public static readonly global::MessagePack.IFormatterResolver Instance = new MagicOnionResolver();
|
||||
|
||||
MagicOnionResolver()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public global::MessagePack.Formatters.IMessagePackFormatter<T> GetFormatter<T>()
|
||||
{
|
||||
return FormatterCache<T>.formatter;
|
||||
}
|
||||
|
||||
static class FormatterCache<T>
|
||||
{
|
||||
public static readonly global::MessagePack.Formatters.IMessagePackFormatter<T> formatter;
|
||||
|
||||
static FormatterCache()
|
||||
{
|
||||
var f = MagicOnionResolverGetFormatterHelper.GetFormatter(typeof(T));
|
||||
if (f != null)
|
||||
{
|
||||
formatter = (global::MessagePack.Formatters.IMessagePackFormatter<T>)f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class MagicOnionResolverGetFormatterHelper
|
||||
{
|
||||
static readonly global::System.Collections.Generic.Dictionary<Type, int> lookup;
|
||||
|
||||
static MagicOnionResolverGetFormatterHelper()
|
||||
{
|
||||
lookup = new global::System.Collections.Generic.Dictionary<Type, int>(3)
|
||||
{
|
||||
{typeof(global::MagicOnion.DynamicArgumentTuple<global::System.Collections.Generic.List<int>, global::System.Collections.Generic.Dictionary<int, string>>), 0 },
|
||||
{typeof(global::System.Collections.Generic.Dictionary<int, string>), 1 },
|
||||
{typeof(global::System.Collections.Generic.List<int>), 2 },
|
||||
};
|
||||
}
|
||||
|
||||
internal static object GetFormatter(Type t)
|
||||
{
|
||||
int key;
|
||||
if (!lookup.TryGetValue(t, out key))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 0: return new global::MagicOnion.DynamicArgumentTupleFormatter<global::System.Collections.Generic.List<int>, global::System.Collections.Generic.Dictionary<int, string>>(default(global::System.Collections.Generic.List<int>), default(global::System.Collections.Generic.Dictionary<int, string>));
|
||||
case 1: return new global::MessagePack.Formatters.DictionaryFormatter<int, string>();
|
||||
case 2: return new global::MessagePack.Formatters.ListFormatter<int>();
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 168
|
||||
#pragma warning restore 219
|
||||
#pragma warning restore 414
|
||||
#pragma warning restore 612
|
||||
#pragma warning restore 618
|
||||
#pragma warning disable 618
|
||||
#pragma warning disable 612
|
||||
#pragma warning disable 414
|
||||
#pragma warning disable 219
|
||||
#pragma warning disable 168
|
||||
|
||||
namespace ChatApp.Shared.Services {
|
||||
using System;
|
||||
using MagicOnion;
|
||||
using MagicOnion.Client;
|
||||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
|
||||
[Ignore]
|
||||
public class ChatServiceClient : MagicOnionClientBase<global::ChatApp.Shared.Services.IChatService>, global::ChatApp.Shared.Services.IChatService
|
||||
{
|
||||
static readonly Method<byte[], byte[]> GenerateExceptionMethod;
|
||||
static readonly Func<RequestContext, ResponseContext> GenerateExceptionDelegate;
|
||||
static readonly Method<byte[], byte[]> SendReportAsyncMethod;
|
||||
static readonly Func<RequestContext, ResponseContext> SendReportAsyncDelegate;
|
||||
|
||||
static ChatServiceClient()
|
||||
{
|
||||
GenerateExceptionMethod = new Method<byte[], byte[]>(MethodType.Unary, "IChatService", "GenerateException", MagicOnionMarshallers.ThroughMarshaller, MagicOnionMarshallers.ThroughMarshaller);
|
||||
GenerateExceptionDelegate = _GenerateException;
|
||||
SendReportAsyncMethod = new Method<byte[], byte[]>(MethodType.Unary, "IChatService", "SendReportAsync", MagicOnionMarshallers.ThroughMarshaller, MagicOnionMarshallers.ThroughMarshaller);
|
||||
SendReportAsyncDelegate = _SendReportAsync;
|
||||
}
|
||||
|
||||
ChatServiceClient()
|
||||
{
|
||||
}
|
||||
|
||||
public ChatServiceClient(CallInvoker callInvoker, MessagePackSerializerOptions serializerOptions, IClientFilter[] filters)
|
||||
: base(callInvoker, serializerOptions, filters)
|
||||
{
|
||||
}
|
||||
|
||||
protected override MagicOnionClientBase<IChatService> Clone()
|
||||
{
|
||||
var clone = new ChatServiceClient();
|
||||
clone.host = this.host;
|
||||
clone.option = this.option;
|
||||
clone.callInvoker = this.callInvoker;
|
||||
clone.serializerOptions = this.serializerOptions;
|
||||
clone.filters = filters;
|
||||
return clone;
|
||||
}
|
||||
|
||||
public new IChatService WithHeaders(Metadata headers)
|
||||
{
|
||||
return base.WithHeaders(headers);
|
||||
}
|
||||
|
||||
public new IChatService WithCancellationToken(System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
return base.WithCancellationToken(cancellationToken);
|
||||
}
|
||||
|
||||
public new IChatService WithDeadline(System.DateTime deadline)
|
||||
{
|
||||
return base.WithDeadline(deadline);
|
||||
}
|
||||
|
||||
public new IChatService WithHost(string host)
|
||||
{
|
||||
return base.WithHost(host);
|
||||
}
|
||||
|
||||
public new IChatService WithOptions(CallOptions option)
|
||||
{
|
||||
return base.WithOptions(option);
|
||||
}
|
||||
|
||||
static ResponseContext _GenerateException(RequestContext __context)
|
||||
{
|
||||
return CreateResponseContext<string, Nil>(__context, GenerateExceptionMethod);
|
||||
}
|
||||
|
||||
public global::MagicOnion.UnaryResult<Nil> GenerateException(string message)
|
||||
{
|
||||
return InvokeAsync<string, Nil>("IChatService/GenerateException", message, GenerateExceptionDelegate);
|
||||
}
|
||||
static ResponseContext _SendReportAsync(RequestContext __context)
|
||||
{
|
||||
return CreateResponseContext<string, Nil>(__context, SendReportAsyncMethod);
|
||||
}
|
||||
|
||||
public global::MagicOnion.UnaryResult<Nil> SendReportAsync(string message)
|
||||
{
|
||||
return InvokeAsync<string, Nil>("IChatService/SendReportAsync", message, SendReportAsyncDelegate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 168
|
||||
#pragma warning restore 219
|
||||
#pragma warning restore 414
|
||||
#pragma warning restore 612
|
||||
#pragma warning restore 618
|
||||
#pragma warning disable 618
|
||||
#pragma warning disable 612
|
||||
#pragma warning disable 414
|
||||
#pragma warning disable 219
|
||||
#pragma warning disable 168
|
||||
|
||||
namespace ChatApp.Shared.Hubs {
|
||||
using Grpc.Core;
|
||||
using Grpc.Core.Logging;
|
||||
using MagicOnion;
|
||||
using MagicOnion.Client;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
[Ignore]
|
||||
public class ChatHubClient : StreamingHubClientBase<global::ChatApp.Shared.Hubs.IChatHub, global::ChatApp.Shared.Hubs.IChatHubReceiver>, global::ChatApp.Shared.Hubs.IChatHub
|
||||
{
|
||||
static readonly Method<byte[], byte[]> method = new Method<byte[], byte[]>(MethodType.DuplexStreaming, "IChatHub", "Connect", MagicOnionMarshallers.ThroughMarshaller, MagicOnionMarshallers.ThroughMarshaller);
|
||||
|
||||
protected override Method<byte[], byte[]> DuplexStreamingAsyncMethod { get { return method; } }
|
||||
|
||||
readonly global::ChatApp.Shared.Hubs.IChatHub __fireAndForgetClient;
|
||||
|
||||
public ChatHubClient(CallInvoker callInvoker, string host, CallOptions option, MessagePackSerializerOptions serializerOptions, ILogger logger)
|
||||
: base(callInvoker, host, option, serializerOptions, logger)
|
||||
{
|
||||
this.__fireAndForgetClient = new FireAndForgetClient(this);
|
||||
}
|
||||
|
||||
public global::ChatApp.Shared.Hubs.IChatHub FireAndForget()
|
||||
{
|
||||
return __fireAndForgetClient;
|
||||
}
|
||||
|
||||
protected override void OnBroadcastEvent(int methodId, ArraySegment<byte> data)
|
||||
{
|
||||
switch (methodId)
|
||||
{
|
||||
case -1297457280: // OnJoin
|
||||
{
|
||||
var result = MessagePackSerializer.Deserialize<string>(data, serializerOptions);
|
||||
receiver.OnJoin(result); break;
|
||||
}
|
||||
case 532410095: // OnLeave
|
||||
{
|
||||
var result = MessagePackSerializer.Deserialize<string>(data, serializerOptions);
|
||||
receiver.OnLeave(result); break;
|
||||
}
|
||||
case -552695459: // OnSendMessage
|
||||
{
|
||||
var result = MessagePackSerializer.Deserialize<global::ChatApp.Shared.MessagePackObjects.MessageResponse>(data, serializerOptions);
|
||||
receiver.OnSendMessage(result); break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnResponseEvent(int methodId, object taskCompletionSource, ArraySegment<byte> data)
|
||||
{
|
||||
switch (methodId)
|
||||
{
|
||||
case -733403293: // JoinAsync
|
||||
{
|
||||
var result = MessagePackSerializer.Deserialize<Nil>(data, serializerOptions);
|
||||
((TaskCompletionSource<Nil>)taskCompletionSource).TrySetResult(result);
|
||||
break;
|
||||
}
|
||||
case 1368362116: // LeaveAsync
|
||||
{
|
||||
var result = MessagePackSerializer.Deserialize<Nil>(data, serializerOptions);
|
||||
((TaskCompletionSource<Nil>)taskCompletionSource).TrySetResult(result);
|
||||
break;
|
||||
}
|
||||
case -601690414: // SendMessageAsync
|
||||
{
|
||||
var result = MessagePackSerializer.Deserialize<Nil>(data, serializerOptions);
|
||||
((TaskCompletionSource<Nil>)taskCompletionSource).TrySetResult(result);
|
||||
break;
|
||||
}
|
||||
case 517938971: // GenerateException
|
||||
{
|
||||
var result = MessagePackSerializer.Deserialize<Nil>(data, serializerOptions);
|
||||
((TaskCompletionSource<Nil>)taskCompletionSource).TrySetResult(result);
|
||||
break;
|
||||
}
|
||||
case -852153394: // SampleMethod
|
||||
{
|
||||
var result = MessagePackSerializer.Deserialize<Nil>(data, serializerOptions);
|
||||
((TaskCompletionSource<Nil>)taskCompletionSource).TrySetResult(result);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task JoinAsync(global::ChatApp.Shared.MessagePackObjects.JoinRequest request)
|
||||
{
|
||||
return WriteMessageWithResponseAsync<global::ChatApp.Shared.MessagePackObjects.JoinRequest, Nil>(-733403293, request);
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task LeaveAsync()
|
||||
{
|
||||
return WriteMessageWithResponseAsync<Nil, Nil>(1368362116, Nil.Default);
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task SendMessageAsync(string message)
|
||||
{
|
||||
return WriteMessageWithResponseAsync<string, Nil>(-601690414, message);
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task GenerateException(string message)
|
||||
{
|
||||
return WriteMessageWithResponseAsync<string, Nil>(517938971, message);
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task SampleMethod(global::System.Collections.Generic.List<int> sampleList, global::System.Collections.Generic.Dictionary<int, string> sampleDictionary)
|
||||
{
|
||||
return WriteMessageWithResponseAsync<DynamicArgumentTuple<global::System.Collections.Generic.List<int>, global::System.Collections.Generic.Dictionary<int, string>>, Nil>(-852153394, new DynamicArgumentTuple<global::System.Collections.Generic.List<int>, global::System.Collections.Generic.Dictionary<int, string>>(sampleList, sampleDictionary));
|
||||
}
|
||||
|
||||
|
||||
class FireAndForgetClient : global::ChatApp.Shared.Hubs.IChatHub
|
||||
{
|
||||
readonly ChatHubClient __parent;
|
||||
|
||||
public FireAndForgetClient(ChatHubClient parentClient)
|
||||
{
|
||||
this.__parent = parentClient;
|
||||
}
|
||||
|
||||
public global::ChatApp.Shared.Hubs.IChatHub FireAndForget()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public Task WaitForDisconnect()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task JoinAsync(global::ChatApp.Shared.MessagePackObjects.JoinRequest request)
|
||||
{
|
||||
return __parent.WriteMessageAsync<global::ChatApp.Shared.MessagePackObjects.JoinRequest>(-733403293, request);
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task LeaveAsync()
|
||||
{
|
||||
return __parent.WriteMessageAsync<Nil>(1368362116, Nil.Default);
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task SendMessageAsync(string message)
|
||||
{
|
||||
return __parent.WriteMessageAsync<string>(-601690414, message);
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task GenerateException(string message)
|
||||
{
|
||||
return __parent.WriteMessageAsync<string>(517938971, message);
|
||||
}
|
||||
|
||||
public global::System.Threading.Tasks.Task SampleMethod(global::System.Collections.Generic.List<int> sampleList, global::System.Collections.Generic.Dictionary<int, string> sampleDictionary)
|
||||
{
|
||||
return __parent.WriteMessageAsync<DynamicArgumentTuple<global::System.Collections.Generic.List<int>, global::System.Collections.Generic.Dictionary<int, string>>>(-852153394, new DynamicArgumentTuple<global::System.Collections.Generic.List<int>, global::System.Collections.Generic.Dictionary<int, string>>(sampleList, sampleDictionary));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 168
|
||||
#pragma warning restore 219
|
||||
#pragma warning restore 414
|
||||
#pragma warning restore 618
|
||||
#pragma warning restore 612
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
// <auto-generated>
|
||||
// THIS (.cs) FILE IS GENERATED BY MPC(MessagePack-CSharp). DO NOT CHANGE IT.
|
||||
// </auto-generated>
|
||||
|
||||
#pragma warning disable 618
|
||||
#pragma warning disable 612
|
||||
#pragma warning disable 414
|
||||
#pragma warning disable 168
|
||||
|
||||
#pragma warning disable SA1200 // Using directives should be placed correctly
|
||||
#pragma warning disable SA1312 // Variable names should begin with lower-case letter
|
||||
#pragma warning disable SA1649 // File name should match first type name
|
||||
|
||||
namespace MessagePack.Resolvers
|
||||
{
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using MessagePack;
|
||||
|
||||
public class GeneratedResolver : global::MessagePack.IFormatterResolver
|
||||
{
|
||||
public static readonly global::MessagePack.IFormatterResolver Instance = new GeneratedResolver();
|
||||
|
||||
private GeneratedResolver()
|
||||
{
|
||||
}
|
||||
|
||||
public global::MessagePack.Formatters.IMessagePackFormatter<T> GetFormatter<T>()
|
||||
{
|
||||
return FormatterCache<T>.Formatter;
|
||||
}
|
||||
|
||||
private static class FormatterCache<T>
|
||||
{
|
||||
internal static readonly global::MessagePack.Formatters.IMessagePackFormatter<T> Formatter;
|
||||
|
||||
static FormatterCache()
|
||||
{
|
||||
var f = GeneratedResolverGetFormatterHelper.GetFormatter(typeof(T));
|
||||
if (f != null)
|
||||
{
|
||||
Formatter = (global::MessagePack.Formatters.IMessagePackFormatter<T>)f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class GeneratedResolverGetFormatterHelper
|
||||
{
|
||||
private static readonly global::System.Collections.Generic.Dictionary<Type, int> lookup;
|
||||
|
||||
static GeneratedResolverGetFormatterHelper()
|
||||
{
|
||||
lookup = new global::System.Collections.Generic.Dictionary<Type, int>(2)
|
||||
{
|
||||
{ typeof(global::ChatApp.Shared.MessagePackObjects.JoinRequest), 0 },
|
||||
{ typeof(global::ChatApp.Shared.MessagePackObjects.MessageResponse), 1 },
|
||||
};
|
||||
}
|
||||
|
||||
internal static object GetFormatter(Type t)
|
||||
{
|
||||
int key;
|
||||
if (!lookup.TryGetValue(t, out key))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 0: return new MessagePack.Formatters.ChatApp.Shared.MessagePackObjects.JoinRequestFormatter();
|
||||
case 1: return new MessagePack.Formatters.ChatApp.Shared.MessagePackObjects.MessageResponseFormatter();
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 168
|
||||
#pragma warning restore 414
|
||||
#pragma warning restore 618
|
||||
#pragma warning restore 612
|
||||
|
||||
#pragma warning restore SA1312 // Variable names should begin with lower-case letter
|
||||
#pragma warning restore SA1200 // Using directives should be placed correctly
|
||||
#pragma warning restore SA1649 // File name should match first type name
|
||||
|
||||
|
||||
|
||||
|
||||
// <auto-generated>
|
||||
// THIS (.cs) FILE IS GENERATED BY MPC(MessagePack-CSharp). DO NOT CHANGE IT.
|
||||
// </auto-generated>
|
||||
|
||||
#pragma warning disable 618
|
||||
#pragma warning disable 612
|
||||
#pragma warning disable 414
|
||||
#pragma warning disable 168
|
||||
|
||||
#pragma warning disable SA1129 // Do not use default value type constructor
|
||||
#pragma warning disable SA1200 // Using directives should be placed correctly
|
||||
#pragma warning disable SA1309 // Field names should not begin with underscore
|
||||
#pragma warning disable SA1312 // Variable names should begin with lower-case letter
|
||||
#pragma warning disable SA1403 // File may only contain a single namespace
|
||||
#pragma warning disable SA1649 // File name should match first type name
|
||||
|
||||
namespace MessagePack.Formatters.ChatApp.Shared.MessagePackObjects
|
||||
{
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using MessagePack;
|
||||
|
||||
public sealed class JoinRequestFormatter : global::MessagePack.Formatters.IMessagePackFormatter<global::ChatApp.Shared.MessagePackObjects.JoinRequest>
|
||||
{
|
||||
|
||||
|
||||
public void Serialize(ref MessagePackWriter writer, global::ChatApp.Shared.MessagePackObjects.JoinRequest value, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
IFormatterResolver formatterResolver = options.Resolver;
|
||||
writer.WriteArrayHeader(2);
|
||||
formatterResolver.GetFormatterWithVerify<string>().Serialize(ref writer, value.RoomName, options);
|
||||
formatterResolver.GetFormatterWithVerify<string>().Serialize(ref writer, value.UserName, options);
|
||||
}
|
||||
|
||||
public global::ChatApp.Shared.MessagePackObjects.JoinRequest Deserialize(ref MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
if (reader.TryReadNil())
|
||||
{
|
||||
throw new InvalidOperationException("typecode is null, struct not supported");
|
||||
}
|
||||
|
||||
IFormatterResolver formatterResolver = options.Resolver;
|
||||
var length = reader.ReadArrayHeader();
|
||||
var __RoomName__ = default(string);
|
||||
var __UserName__ = default(string);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
var key = i;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 0:
|
||||
__RoomName__ = formatterResolver.GetFormatterWithVerify<string>().Deserialize(ref reader, options);
|
||||
break;
|
||||
case 1:
|
||||
__UserName__ = formatterResolver.GetFormatterWithVerify<string>().Deserialize(ref reader, options);
|
||||
break;
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var ____result = new global::ChatApp.Shared.MessagePackObjects.JoinRequest();
|
||||
____result.RoomName = __RoomName__;
|
||||
____result.UserName = __UserName__;
|
||||
return ____result;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MessageResponseFormatter : global::MessagePack.Formatters.IMessagePackFormatter<global::ChatApp.Shared.MessagePackObjects.MessageResponse>
|
||||
{
|
||||
|
||||
|
||||
public void Serialize(ref MessagePackWriter writer, global::ChatApp.Shared.MessagePackObjects.MessageResponse value, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
IFormatterResolver formatterResolver = options.Resolver;
|
||||
writer.WriteArrayHeader(2);
|
||||
formatterResolver.GetFormatterWithVerify<string>().Serialize(ref writer, value.UserName, options);
|
||||
formatterResolver.GetFormatterWithVerify<string>().Serialize(ref writer, value.Message, options);
|
||||
}
|
||||
|
||||
public global::ChatApp.Shared.MessagePackObjects.MessageResponse Deserialize(ref MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options)
|
||||
{
|
||||
if (reader.TryReadNil())
|
||||
{
|
||||
throw new InvalidOperationException("typecode is null, struct not supported");
|
||||
}
|
||||
|
||||
IFormatterResolver formatterResolver = options.Resolver;
|
||||
var length = reader.ReadArrayHeader();
|
||||
var __UserName__ = default(string);
|
||||
var __Message__ = default(string);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
var key = i;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 0:
|
||||
__UserName__ = formatterResolver.GetFormatterWithVerify<string>().Deserialize(ref reader, options);
|
||||
break;
|
||||
case 1:
|
||||
__Message__ = formatterResolver.GetFormatterWithVerify<string>().Deserialize(ref reader, options);
|
||||
break;
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var ____result = new global::ChatApp.Shared.MessagePackObjects.MessageResponse();
|
||||
____result.UserName = __UserName__;
|
||||
____result.Message = __Message__;
|
||||
return ____result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 168
|
||||
#pragma warning restore 414
|
||||
#pragma warning restore 618
|
||||
#pragma warning restore 612
|
||||
|
||||
#pragma warning restore SA1129 // Do not use default value type constructor
|
||||
#pragma warning restore SA1200 // Using directives should be placed correctly
|
||||
#pragma warning restore SA1309 // Field names should not begin with underscore
|
||||
#pragma warning restore SA1312 // Variable names should begin with lower-case letter
|
||||
#pragma warning restore SA1403 // File may only contain a single namespace
|
||||
#pragma warning restore SA1649 // File name should match first type name
|
||||
|
||||
|
|
@ -11,8 +11,7 @@ namespace Assets.Scripts
|
|||
{
|
||||
// NOTE: Currently, CompositeResolver doesn't work on Unity IL2CPP build. Use StaticCompositeResolver instead of it.
|
||||
StaticCompositeResolver.Instance.Register(
|
||||
MagicOnion.Resolvers.MagicOnionResolver.Instance,
|
||||
MessagePack.Resolvers.GeneratedResolver.Instance,
|
||||
MathResolver.Instance,
|
||||
BuiltinResolver.Instance,
|
||||
PrimitiveObjectResolver.Instance
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
public interface IResponseContext : IDisposable
|
||||
{
|
||||
Task<Metadata> ResponseHeadersAsync { get; }
|
||||
Status GetStatus();
|
||||
Metadata GetTrailers();
|
||||
Type ResponseType { get; }
|
||||
}
|
||||
|
||||
public interface IResponseContext<T> : IResponseContext
|
||||
{
|
||||
Task<T> ResponseAsync { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapped AsyncClientStreamingCall.
|
||||
/// </summary>
|
||||
public struct ClientStreamingResult<TRequest, TResponse> : IDisposable
|
||||
{
|
||||
internal readonly TResponse rawValue;
|
||||
internal readonly bool hasRawValue;
|
||||
readonly AsyncClientStreamingCall<byte[], byte[]> inner;
|
||||
readonly IClientStreamWriter<TRequest> requestStream;
|
||||
readonly MessagePackSerializerOptions serializerOptions;
|
||||
|
||||
public ClientStreamingResult(TResponse rawValue)
|
||||
{
|
||||
this.hasRawValue = true;
|
||||
this.rawValue = rawValue;
|
||||
this.inner = null;
|
||||
this.requestStream = null;
|
||||
this.serializerOptions = null;
|
||||
}
|
||||
|
||||
public ClientStreamingResult(AsyncClientStreamingCall<byte[], byte[]> inner, IClientStreamWriter<TRequest> requestStream, MessagePackSerializerOptions serializerOptions)
|
||||
{
|
||||
this.hasRawValue = false;
|
||||
this.rawValue = default(TResponse);
|
||||
this.inner = inner;
|
||||
this.requestStream = requestStream;
|
||||
this.serializerOptions = serializerOptions;
|
||||
}
|
||||
|
||||
async Task<TResponse> Deserialize()
|
||||
{
|
||||
var bytes = await inner.ResponseAsync.ConfigureAwait(false);
|
||||
return MessagePackSerializer.Deserialize<TResponse>(bytes, serializerOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronous call result.
|
||||
/// </summary>
|
||||
public Task<TResponse> ResponseAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
if (hasRawValue)
|
||||
{
|
||||
return Task.FromResult(rawValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Deserialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronous access to response headers.
|
||||
/// </summary>
|
||||
public Task<Metadata> ResponseHeadersAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.inner.ResponseHeadersAsync;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Async stream to send streaming requests.
|
||||
/// </summary>
|
||||
public IClientStreamWriter<TRequest> RequestStream
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.requestStream;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows awaiting this object directly.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TaskAwaiter<TResponse> GetAwaiter()
|
||||
{
|
||||
return ResponseAsync.GetAwaiter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the call status if the call has already finished.
|
||||
/// Throws InvalidOperationException otherwise.
|
||||
/// </summary>
|
||||
public Status GetStatus()
|
||||
{
|
||||
return this.inner.GetStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the call trailing metadata if the call has already finished.
|
||||
/// Throws InvalidOperationException otherwise.
|
||||
/// </summary>
|
||||
public Metadata GetTrailers()
|
||||
{
|
||||
return this.inner.GetTrailers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides means to cleanup after the call.
|
||||
/// If the call has already finished normally (request stream has been completed and call result has been received), doesn't do anything.
|
||||
/// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call.
|
||||
/// As a result, all resources being used by the call should be released eventually.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Normally, there is no need for you to dispose the call unless you want to utilize the
|
||||
/// "Cancel" semantics of invoking <c>Dispose</c>.
|
||||
/// </remarks>
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.inner != null)
|
||||
{
|
||||
this.inner.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1e92d02db742a454fa25774f217806cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security;
|
||||
|
||||
namespace MagicOnion.CompilerServices
|
||||
{
|
||||
public struct AsyncUnaryResultMethodBuilder<T>
|
||||
{
|
||||
private AsyncTaskMethodBuilder<T> methodBuilder;
|
||||
private T result;
|
||||
private bool haveResult;
|
||||
private bool useBuilder;
|
||||
|
||||
public static AsyncUnaryResultMethodBuilder<T> Create()
|
||||
{
|
||||
return new AsyncUnaryResultMethodBuilder<T>() { methodBuilder = AsyncTaskMethodBuilder<T>.Create() };
|
||||
}
|
||||
|
||||
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
|
||||
{
|
||||
methodBuilder.Start(ref stateMachine); // will provide the right ExecutionContext semantics
|
||||
}
|
||||
|
||||
public void SetStateMachine(IAsyncStateMachine stateMachine)
|
||||
{
|
||||
methodBuilder.SetStateMachine(stateMachine);
|
||||
}
|
||||
|
||||
public void SetResult(T result)
|
||||
{
|
||||
if (useBuilder)
|
||||
{
|
||||
methodBuilder.SetResult(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.result = result;
|
||||
haveResult = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetException(Exception exception)
|
||||
{
|
||||
methodBuilder.SetException(exception);
|
||||
}
|
||||
|
||||
public UnaryResult<T> Task
|
||||
{
|
||||
get
|
||||
{
|
||||
if (haveResult)
|
||||
{
|
||||
return new UnaryResult<T>(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
useBuilder = true;
|
||||
return new UnaryResult<T>(methodBuilder.Task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
|
||||
where TAwaiter : INotifyCompletion
|
||||
where TStateMachine : IAsyncStateMachine
|
||||
{
|
||||
useBuilder = true;
|
||||
methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
|
||||
where TAwaiter : ICriticalNotifyCompletion
|
||||
where TStateMachine : IAsyncStateMachine
|
||||
{
|
||||
useBuilder = true;
|
||||
methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 975c42469777f414fae46186971f0dc8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapped AsyncDuplexStreamingCall.
|
||||
/// </summary>
|
||||
public struct DuplexStreamingResult<TRequest, TResponse> : IDisposable
|
||||
{
|
||||
readonly AsyncDuplexStreamingCall<byte[], byte[]> inner;
|
||||
readonly IClientStreamWriter<TRequest> requestStream;
|
||||
readonly IAsyncStreamReader<TResponse> responseStream;
|
||||
|
||||
public DuplexStreamingResult(AsyncDuplexStreamingCall<byte[], byte[]> inner, IClientStreamWriter<TRequest> requestStream, IAsyncStreamReader<TResponse> responseStream, MessagePackSerializerOptions serializerOptions)
|
||||
{
|
||||
this.inner = inner;
|
||||
this.requestStream = requestStream;
|
||||
this.responseStream = responseStream;
|
||||
}
|
||||
|
||||
public AsyncDuplexStreamingCall<byte[], byte[]> RawStreamingCall => inner;
|
||||
|
||||
/// <summary>
|
||||
/// Async stream to read streaming responses.
|
||||
/// </summary>
|
||||
public IAsyncStreamReader<TResponse> ResponseStream
|
||||
{
|
||||
get
|
||||
{
|
||||
return responseStream;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Async stream to send streaming requests.
|
||||
/// </summary>
|
||||
public IClientStreamWriter<TRequest> RequestStream
|
||||
{
|
||||
get
|
||||
{
|
||||
return requestStream;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronous access to response headers.
|
||||
/// </summary>
|
||||
public Task<Metadata> ResponseHeadersAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.inner.ResponseHeadersAsync;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the call status if the call has already finished.
|
||||
/// Throws InvalidOperationException otherwise.
|
||||
/// </summary>
|
||||
public Status GetStatus()
|
||||
{
|
||||
return this.inner.GetStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the call trailing metadata if the call has already finished.
|
||||
/// Throws InvalidOperationException otherwise.
|
||||
/// </summary>
|
||||
public Metadata GetTrailers()
|
||||
{
|
||||
return this.inner.GetTrailers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides means to cleanup after the call.
|
||||
/// If the call has already finished normally (request stream has been completed and response stream has been fully read), doesn't do anything.
|
||||
/// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call.
|
||||
/// As a result, all resources being used by the call should be released eventually.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Normally, there is no need for you to dispose the call unless you want to utilize the
|
||||
/// "Cancel" semantics of invoking <c>Dispose</c>.
|
||||
/// </remarks>
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.inner != null)
|
||||
{
|
||||
this.inner.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 383e96f82d4d6244b951f0fc83d49b63
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
/// <summary>
|
||||
/// instruction for moc.exe, surround #if symbol with output code.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
|
||||
public class GenerateDefineDebugAttribute : Attribute
|
||||
{
|
||||
public GenerateDefineDebugAttribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ab20e13a7e0b6b644a42dbfa3b44afd3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
// used for MagicOnionEngine assembly scan for boostup analyze speed.
|
||||
public interface IServiceMarker
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface IService<TSelf> : IServiceMarker
|
||||
{
|
||||
TSelf WithOptions(CallOptions option);
|
||||
TSelf WithHeaders(Metadata headers);
|
||||
TSelf WithDeadline(DateTime deadline);
|
||||
TSelf WithCancellationToken(CancellationToken cancellationToken);
|
||||
TSelf WithHost(string host);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 56677a2edb7ea644faf4846ad283b007
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
public interface IStreamingHubMarker
|
||||
{
|
||||
}
|
||||
|
||||
public interface IStreamingHub<TSelf, TReceiver> : IStreamingHubMarker, IServiceMarker
|
||||
{
|
||||
TSelf FireAndForget(); // if changed to get-only property, intellisense does not work on VS2017.
|
||||
Task DisposeAsync();
|
||||
Task WaitForDisconnect();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5d0a5fcfa0834b84ea6ff4d77e478fb9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
/// <summary>
|
||||
/// Don't register on MagicOnionEngine.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,AllowMultiple = false,Inherited = false)]
|
||||
public class IgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0d13f2ed066fd874b8749ca248f42c51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"name": "MagicOnion.Abstractions",
|
||||
"references": [
|
||||
"MessagePack"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 62b9d94cd08d5d047b266d42e8684cb8
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 33588a48f556fba45b238f907a8ebc38
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace MagicOnion.Server.Hubs
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class MethodIdAttribute : Attribute
|
||||
{
|
||||
public readonly int MethodId;
|
||||
|
||||
public MethodIdAttribute(int methodId)
|
||||
{
|
||||
MethodId = methodId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1752261f18dd5f749b27216b7cbe81e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapped AsyncServerStreamingCall.
|
||||
/// </summary>
|
||||
public struct ServerStreamingResult<TResponse> : IDisposable
|
||||
{
|
||||
readonly AsyncServerStreamingCall<byte[]> inner;
|
||||
readonly IAsyncStreamReader<TResponse> responseStream;
|
||||
|
||||
public ServerStreamingResult(AsyncServerStreamingCall<byte[]> inner, IAsyncStreamReader<TResponse> responseStream, MessagePackSerializerOptions serializerOptions)
|
||||
{
|
||||
this.inner = inner;
|
||||
this.responseStream = responseStream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Async stream to read streaming responses.
|
||||
/// </summary>
|
||||
public IAsyncStreamReader<TResponse> ResponseStream
|
||||
{
|
||||
get
|
||||
{
|
||||
return responseStream;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronous access to response headers.
|
||||
/// </summary>
|
||||
public Task<Metadata> ResponseHeadersAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.inner.ResponseHeadersAsync;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the call status if the call has already finished.
|
||||
/// Throws InvalidOperationException otherwise.
|
||||
/// </summary>
|
||||
public Status GetStatus()
|
||||
{
|
||||
return this.inner.GetStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the call trailing metadata if the call has already finished.
|
||||
/// Throws InvalidOperationException otherwise.
|
||||
/// </summary>
|
||||
public Metadata GetTrailers()
|
||||
{
|
||||
return this.inner.GetTrailers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides means to cleanup after the call.
|
||||
/// If the call has already finished normally (response stream has been fully read), doesn't do anything.
|
||||
/// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call.
|
||||
/// As a result, all resources being used by the call should be released eventually.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Normally, there is no need for you to dispose the call unless you want to utilize the
|
||||
/// "Cancel" semantics of invoking <c>Dispose</c>.
|
||||
/// </remarks>
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.inner != null)
|
||||
{
|
||||
this.inner.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 46a21c751ab9a4f4caf74e806bfe2bea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MagicOnion.Client;
|
||||
using MagicOnion.CompilerServices; // require this using in AsyncMethodBuilder
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapped AsyncUnaryCall.
|
||||
/// </summary>
|
||||
#if NON_UNITY || (CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)))
|
||||
[AsyncMethodBuilder(typeof(AsyncUnaryResultMethodBuilder<>))]
|
||||
#endif
|
||||
public struct UnaryResult<TResponse>
|
||||
{
|
||||
internal readonly bool hasRawValue; // internal
|
||||
internal readonly TResponse rawValue; // internal
|
||||
internal readonly Task<TResponse> rawTaskValue; // internal
|
||||
|
||||
readonly Task<IResponseContext<TResponse>> response;
|
||||
|
||||
public UnaryResult(TResponse rawValue)
|
||||
{
|
||||
this.hasRawValue = true;
|
||||
this.rawValue = rawValue;
|
||||
this.rawTaskValue = null;
|
||||
this.response = null;
|
||||
}
|
||||
|
||||
public UnaryResult(Task<TResponse> rawTaskValue)
|
||||
{
|
||||
this.hasRawValue = true;
|
||||
this.rawValue = default(TResponse);
|
||||
this.rawTaskValue = rawTaskValue;
|
||||
this.response = null;
|
||||
}
|
||||
|
||||
public UnaryResult(Task<IResponseContext<TResponse>> response)
|
||||
{
|
||||
this.hasRawValue = false;
|
||||
this.rawValue = default(TResponse);
|
||||
this.rawTaskValue = null;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronous call result.
|
||||
/// </summary>
|
||||
public Task<TResponse> ResponseAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!hasRawValue)
|
||||
{
|
||||
return UnwrapResponse();
|
||||
}
|
||||
else if (rawTaskValue != null)
|
||||
{
|
||||
return rawTaskValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Task.FromResult(rawValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronous access to response headers.
|
||||
/// </summary>
|
||||
public Task<Metadata> ResponseHeadersAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
return UnwrapResponseHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
async Task<TResponse> UnwrapResponse()
|
||||
{
|
||||
var ctx = await response.ConfigureAwait(false);
|
||||
return await ctx.ResponseAsync.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
async Task<Metadata> UnwrapResponseHeaders()
|
||||
{
|
||||
var ctx = await response.ConfigureAwait(false);
|
||||
return await ctx.ResponseHeadersAsync.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
async void UnwrapDispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
var ctx = await response.ConfigureAwait(false);
|
||||
ctx.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
IResponseContext<TResponse> TryUnwrap()
|
||||
{
|
||||
if (!response.IsCompleted)
|
||||
{
|
||||
throw new InvalidOperationException("UnaryResult request is not yet completed, please await before call this.");
|
||||
}
|
||||
|
||||
return response.Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows awaiting this object directly.
|
||||
/// </summary>
|
||||
public TaskAwaiter<TResponse> GetAwaiter()
|
||||
{
|
||||
return ResponseAsync.GetAwaiter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the call status if the call has already finished.
|
||||
/// Throws InvalidOperationException otherwise.
|
||||
/// </summary>
|
||||
public Status GetStatus()
|
||||
{
|
||||
return TryUnwrap().GetStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the call trailing metadata if the call has already finished.
|
||||
/// Throws InvalidOperationException otherwise.
|
||||
/// </summary>
|
||||
public Metadata GetTrailers()
|
||||
{
|
||||
return TryUnwrap().GetTrailers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides means to cleanup after the call.
|
||||
/// If the call has already finished normally (request stream has been completed and call result has been received), doesn't do anything.
|
||||
/// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call.
|
||||
/// As a result, all resources being used by the call should be released eventually.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Normally, there is no need for you to dispose the call unless you want to utilize the
|
||||
/// "Cancel" semantics of invoking <c>Dispose</c>.
|
||||
/// </remarks>
|
||||
public void Dispose()
|
||||
{
|
||||
if (!response.IsCompleted)
|
||||
{
|
||||
UnwrapDispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
response.Result.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cc0fe0c16ad63fd489a131a76e925b08
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 54a7a4436d8b4f54c908f4bdc47a3d62
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
public static class ChannelExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Safety way for subscribe streaming events.
|
||||
/// </summary>
|
||||
public static void RegisterStreamingSubscription(this Channel channel, IDisposable subscription)
|
||||
{
|
||||
channel.ShutdownToken.Register(() => subscription.Dispose());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 88d6659672dcc9e408775f1fcaa6dea3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "MagicOnion.Unity",
|
||||
"references": [
|
||||
"MagicOnion.Abstractions",
|
||||
"MagicOnion"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 350d0af80fb7b7947a59de66ab477547
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
using Grpc.Core.Logging;
|
||||
using System;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
public class UnityDebugLogger : ILogger
|
||||
{
|
||||
readonly Type forType;
|
||||
readonly string forTypeString;
|
||||
readonly bool errorToWarn = true; // default is true(gRPC internal log show to warn)
|
||||
|
||||
public UnityDebugLogger()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public UnityDebugLogger(bool errorToWarn)
|
||||
: this(null)
|
||||
{
|
||||
this.errorToWarn = errorToWarn;
|
||||
}
|
||||
|
||||
protected UnityDebugLogger(Type forType)
|
||||
{
|
||||
this.forType = forType;
|
||||
if (forType != null)
|
||||
{
|
||||
var namespaceStr = forType.Namespace ?? "";
|
||||
if (namespaceStr.Length > 0)
|
||||
{
|
||||
namespaceStr += ".";
|
||||
}
|
||||
this.forTypeString = namespaceStr + forType.Name + " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.forTypeString = "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a logger associated with the specified type.
|
||||
/// </summary>
|
||||
public virtual ILogger ForType<T>()
|
||||
{
|
||||
if (typeof(T) == forType)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
return new UnityDebugLogger(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>Logs a message with severity Debug.</summary>
|
||||
public void Debug(string message)
|
||||
{
|
||||
UnityEngine.Debug.Log(BuildMessage(message));
|
||||
}
|
||||
|
||||
/// <summary>Logs a formatted message with severity Debug.</summary>
|
||||
public void Debug(string format, params object[] formatArgs)
|
||||
{
|
||||
UnityEngine.Debug.Log(BuildMessage(format, formatArgs));
|
||||
}
|
||||
|
||||
/// <summary>Logs a message with severity Info.</summary>
|
||||
public void Info(string message)
|
||||
{
|
||||
UnityEngine.Debug.Log(BuildMessage(message));
|
||||
}
|
||||
|
||||
/// <summary>Logs a formatted message with severity Info.</summary>
|
||||
public void Info(string format, params object[] formatArgs)
|
||||
{
|
||||
UnityEngine.Debug.Log(BuildMessage(format, formatArgs));
|
||||
}
|
||||
|
||||
/// <summary>Logs a message with severity Warning.</summary>
|
||||
public void Warning(string message)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(BuildMessage(message));
|
||||
}
|
||||
|
||||
/// <summary>Logs a formatted message with severity Warning.</summary>
|
||||
public void Warning(string format, params object[] formatArgs)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(BuildMessage(format, formatArgs));
|
||||
}
|
||||
|
||||
/// <summary>Logs a message and an associated exception with severity Warning.</summary>
|
||||
public void Warning(Exception exception, string message)
|
||||
{
|
||||
Warning(message + " " + exception);
|
||||
}
|
||||
|
||||
/// <summary>Logs a message with severity Error.</summary>
|
||||
public void Error(string message)
|
||||
{
|
||||
if (errorToWarn)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(BuildMessage(message));
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Debug.LogError(BuildMessage(message));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Logs a formatted message with severity Error.</summary>
|
||||
public void Error(string format, params object[] formatArgs)
|
||||
{
|
||||
if (errorToWarn)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(BuildMessage(format, formatArgs));
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Debug.LogError(BuildMessage(format, formatArgs));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Logs a message and an associated exception with severity Error.</summary>
|
||||
public void Error(Exception exception, string message)
|
||||
{
|
||||
Error(message + " " + exception);
|
||||
}
|
||||
|
||||
/// <summary>Gets the type associated with this logger.</summary>
|
||||
protected Type AssociatedType
|
||||
{
|
||||
get { return forType; }
|
||||
}
|
||||
|
||||
string BuildMessage(string message)
|
||||
{
|
||||
if (forType != null)
|
||||
{
|
||||
return forTypeString + message;
|
||||
}
|
||||
else
|
||||
{
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
string BuildMessage(string format, object[] args)
|
||||
{
|
||||
if (forType != null)
|
||||
{
|
||||
return forTypeString + string.Format(format, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Format(format, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5a9b20988ba163244a107c806f58c14f
|
||||
timeCreated: 1482380673
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1d7d16d9066daaf47a8b3c4af6ecfed3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
public class AsyncLock
|
||||
{
|
||||
readonly SemaphoreSlim semaphore;
|
||||
|
||||
#if NON_UNITY
|
||||
public static readonly ValueTask<LockReleaser> EmptyLock = new ValueTask<LockReleaser>(new LockReleaser(null));
|
||||
#endif
|
||||
|
||||
public AsyncLock()
|
||||
{
|
||||
this.semaphore = new SemaphoreSlim(1, 1);
|
||||
}
|
||||
|
||||
#if NON_UNITY
|
||||
public async ValueTask<LockReleaser> LockAsync()
|
||||
#else
|
||||
public async Task<LockReleaser> LockAsync()
|
||||
#endif
|
||||
{
|
||||
await semaphore.WaitAsync().ConfigureAwait(false);
|
||||
return new LockReleaser(semaphore);
|
||||
}
|
||||
|
||||
public struct LockReleaser : IDisposable
|
||||
{
|
||||
readonly SemaphoreSlim semaphore;
|
||||
|
||||
public LockReleaser(SemaphoreSlim semaphore)
|
||||
{
|
||||
this.semaphore = semaphore;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
semaphore?.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9a1fdda349d00b84596da99fbda0426d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
public static class AsyncStreamReaderExtensions
|
||||
{
|
||||
public static async Task ForEachAsync<T>(this IAsyncStreamReader<T> stream, Action<T> action, CancellationToken cancellation = default(CancellationToken))
|
||||
{
|
||||
using (stream as IDisposable)
|
||||
{
|
||||
while (!cancellation.IsCancellationRequested && await stream.MoveNext(cancellation))
|
||||
{
|
||||
action(stream.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ForEachAsync<T>(this IAsyncStreamReader<T> stream, Func<T, Task> asyncAction, CancellationToken cancellation = default(CancellationToken))
|
||||
{
|
||||
using (stream as IDisposable)
|
||||
{
|
||||
while (!cancellation.IsCancellationRequested && await stream.MoveNext(cancellation))
|
||||
{
|
||||
await asyncAction(stream.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eccd314ac5c4f71499ebad65fd6d3ecf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f41f5b00e235ac44d8d3aaea561952a3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
public interface IClientFilter
|
||||
{
|
||||
ValueTask<ResponseContext> SendAsync(RequestContext context, Func<RequestContext, ValueTask<ResponseContext>> next);
|
||||
}
|
||||
|
||||
public abstract class RequestContext
|
||||
{
|
||||
static readonly Func<byte[], byte[]> DefaultMutator = xs => xs;
|
||||
|
||||
public string MethodPath { get; }
|
||||
public CallOptions CallOptions { get; }
|
||||
public Type ResponseType { get; }
|
||||
public abstract Type RequestType { get; }
|
||||
public Func<byte[], byte[]> RequestMutator { get; private set; }
|
||||
public Func<byte[], byte[]> ResponseMutator { get; private set; }
|
||||
|
||||
Dictionary<string, object> items;
|
||||
public IDictionary<string, object> Items
|
||||
{
|
||||
get
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
items = new Dictionary<string, object>();
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
// internal use to avoid lambda capture.
|
||||
internal MagicOnionClientBase Client { get; }
|
||||
internal IClientFilter[] Filters { get; }
|
||||
internal Func<RequestContext, ResponseContext> RequestMethod { get; }
|
||||
|
||||
internal RequestContext(MagicOnionClientBase client, string methodPath, CallOptions callOptions, Type responseType, IClientFilter[] filters, Func<RequestContext, ResponseContext> requestMethod)
|
||||
{
|
||||
this.Client = client;
|
||||
this.MethodPath = methodPath;
|
||||
this.CallOptions = callOptions;
|
||||
this.ResponseType = responseType;
|
||||
this.Filters = filters;
|
||||
this.RequestMethod = requestMethod;
|
||||
this.RequestMutator = DefaultMutator;
|
||||
this.ResponseMutator = DefaultMutator;
|
||||
}
|
||||
|
||||
public void SetRequestMutator(Func<byte[], byte[]> mutator)
|
||||
{
|
||||
this.RequestMutator = mutator;
|
||||
}
|
||||
|
||||
public void SetResponseMutator(Func<byte[], byte[]> mutator)
|
||||
{
|
||||
this.ResponseMutator = mutator;
|
||||
}
|
||||
}
|
||||
|
||||
public class RequestContext<T> : RequestContext
|
||||
{
|
||||
public T Request { get; }
|
||||
public override Type RequestType => typeof(T);
|
||||
|
||||
public RequestContext(T request, MagicOnionClientBase client, string methodPath, CallOptions callOptions, Type responseType, IClientFilter[] filters, Func<RequestContext, ResponseContext> requestMethod)
|
||||
: base(client, methodPath, callOptions, responseType, filters, requestMethod)
|
||||
{
|
||||
this.Request = request;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ResponseContext : IResponseContext
|
||||
{
|
||||
static readonly Func<byte[], byte[]> DefaultMutator = xs => xs;
|
||||
|
||||
public abstract Task<Metadata> ResponseHeadersAsync { get; }
|
||||
public abstract Status GetStatus();
|
||||
public abstract Metadata GetTrailers();
|
||||
public abstract void Dispose();
|
||||
public abstract Type ResponseType { get; }
|
||||
public Func<byte[], byte[]> ResponseMutator { get; private set; }
|
||||
|
||||
public abstract Task<ResponseContext> WaitResponseAsync();
|
||||
|
||||
public ResponseContext<T> As<T>()
|
||||
{
|
||||
return this as ResponseContext<T>;
|
||||
}
|
||||
|
||||
public Task<T> GetResponseAs<T>()
|
||||
{
|
||||
var t = this as ResponseContext<T>;
|
||||
if (t == null) return Task.FromResult(default(T));
|
||||
|
||||
return t.ResponseAsync;
|
||||
}
|
||||
|
||||
public ResponseContext()
|
||||
{
|
||||
this.ResponseMutator = DefaultMutator;
|
||||
}
|
||||
|
||||
public void SetResponseMutator(Func<byte[], byte[]> mutator)
|
||||
{
|
||||
this.ResponseMutator = mutator;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ResponseContext<T> : ResponseContext, IResponseContext<T>
|
||||
{
|
||||
readonly AsyncUnaryCall<byte[]> inner;
|
||||
readonly MessagePackSerializerOptions serializerOptions;
|
||||
readonly bool isMock;
|
||||
bool deserialized;
|
||||
|
||||
T responseObject; // cache value.
|
||||
|
||||
// mock
|
||||
readonly Metadata trailers;
|
||||
readonly Metadata responseHeaders;
|
||||
readonly Status status;
|
||||
|
||||
public ResponseContext(AsyncUnaryCall<byte[]> inner, MessagePackSerializerOptions serializerOptions)
|
||||
: base()
|
||||
{
|
||||
this.isMock = false;
|
||||
this.inner = inner;
|
||||
this.serializerOptions = serializerOptions;
|
||||
}
|
||||
|
||||
public ResponseContext(T responseObject)
|
||||
: this(responseObject, new Metadata(), new Metadata(), Status.DefaultSuccess)
|
||||
{
|
||||
}
|
||||
|
||||
public ResponseContext(T responseObject, Metadata trailers, Metadata responseHeaders, Status status)
|
||||
: base()
|
||||
{
|
||||
this.isMock = true;
|
||||
this.responseObject = responseObject;
|
||||
this.trailers = trailers;
|
||||
this.responseHeaders = responseHeaders;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
async Task<T> Deserialize()
|
||||
{
|
||||
if (deserialized)
|
||||
{
|
||||
return responseObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
var bytes = await inner.ResponseAsync.ConfigureAwait(false);
|
||||
responseObject = MessagePackSerializer.Deserialize<T>(this.ResponseMutator(bytes), serializerOptions);
|
||||
deserialized = true;
|
||||
return responseObject;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<T> ResponseAsync => !isMock ? Deserialize() : Task.FromResult(responseObject);
|
||||
|
||||
public override async Task<ResponseContext> WaitResponseAsync()
|
||||
{
|
||||
await ResponseAsync;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override Type ResponseType => typeof(T);
|
||||
|
||||
public override Task<Metadata> ResponseHeadersAsync => !isMock ? inner.ResponseHeadersAsync : Task.FromResult(responseHeaders);
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (!isMock)
|
||||
{
|
||||
inner.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public override Status GetStatus()
|
||||
{
|
||||
return !isMock ? inner.GetStatus() : status;
|
||||
}
|
||||
|
||||
public override Metadata GetTrailers()
|
||||
{
|
||||
return !isMock ? inner.GetTrailers() : trailers;
|
||||
}
|
||||
|
||||
public ResponseContext<T> WithNewResult(T result)
|
||||
{
|
||||
if (isMock)
|
||||
{
|
||||
return new ResponseContext<T>(result, trailers, responseHeaders, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newContext = new ResponseContext<T>(inner, serializerOptions);
|
||||
newContext.deserialized = true;
|
||||
newContext.responseObject = result;
|
||||
return newContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d0190394f8c415b4b84aa1b95b993369
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,628 +0,0 @@
|
|||
#if NON_UNITY || !NET_STANDARD_2_0
|
||||
|
||||
using Grpc.Core;
|
||||
using MagicOnion.Utils;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class DynamicClientAssemblyHolder
|
||||
{
|
||||
public const string ModuleName = "MagicOnion.Client.DynamicClient";
|
||||
|
||||
readonly static DynamicAssembly assembly;
|
||||
public static DynamicAssembly Assembly { get { return assembly; } }
|
||||
|
||||
static DynamicClientAssemblyHolder()
|
||||
{
|
||||
assembly = new DynamicAssembly(ModuleName);
|
||||
}
|
||||
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
|
||||
public static AssemblyBuilder Save()
|
||||
{
|
||||
return assembly.Save();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class DynamicClientBuilder<T>
|
||||
where T : IService<T>
|
||||
{
|
||||
public static readonly Type ClientType;
|
||||
static readonly Type bytesMethod = typeof(Method<,>).MakeGenericType(new[] { typeof(byte[]), typeof(byte[]) });
|
||||
static readonly FieldInfo throughMarshaller = typeof(MagicOnionMarshallers).GetField("ThroughMarshaller", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
static readonly FieldInfo nilBytes = typeof(MagicOnionMarshallers).GetField("UnsafeNilBytes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
static readonly MethodInfo callMessagePackSerialize = typeof(MessagePackSerializer).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
|
||||
.First(x => x.Name == "Serialize" && x.GetParameters().Length == 3 && x.ReturnType == typeof(byte[]));
|
||||
static readonly MethodInfo callCancellationTokenNone = typeof(CancellationToken).GetProperty("None", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetGetMethod();
|
||||
|
||||
static DynamicClientBuilder()
|
||||
{
|
||||
var t = typeof(T);
|
||||
var ti = t.GetTypeInfo();
|
||||
if (!ti.IsInterface) throw new Exception("Client Proxy only allows interface. Type:" + ti.Name);
|
||||
|
||||
var asm = DynamicClientAssemblyHolder.Assembly;
|
||||
var methodDefinitions = SearchDefinitions(t);
|
||||
|
||||
var parentType = typeof(MagicOnionClientBase<>).MakeGenericType(t);
|
||||
var typeBuilder = asm.DefineType($"{DynamicClientAssemblyHolder.ModuleName}.{ti.FullName}Client", TypeAttributes.Public, parentType, new Type[] { t });
|
||||
|
||||
// Set `IgnoreAttribute` to the generated client type. Hides generated-types from building MagicOnion service definitions.
|
||||
typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(IgnoreAttribute).GetConstructor(Array.Empty<Type>()), Array.Empty<object>()));
|
||||
|
||||
DefineStaticFields(typeBuilder, methodDefinitions);
|
||||
DefineStaticConstructor(typeBuilder, t, methodDefinitions);
|
||||
var emptyCtor = DefineConstructors(typeBuilder, methodDefinitions);
|
||||
DefineMethods(typeBuilder, t, methodDefinitions, emptyCtor);
|
||||
|
||||
ClientType = typeBuilder.CreateTypeInfo().AsType();
|
||||
}
|
||||
|
||||
static MethodDefinition[] SearchDefinitions(Type interfaceType)
|
||||
{
|
||||
return interfaceType
|
||||
.GetInterfaces()
|
||||
.Concat(new[] { interfaceType })
|
||||
.SelectMany(x => x.GetMethods())
|
||||
.Where(x =>
|
||||
{
|
||||
var methodInfo = x;
|
||||
if (methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_") || methodInfo.Name.StartsWith("get_"))) return false;
|
||||
if (methodInfo.GetCustomAttribute<IgnoreAttribute>(false) != null) return false; // ignore
|
||||
|
||||
var methodName = methodInfo.Name;
|
||||
if (methodName == "Equals"
|
||||
|| methodName == "GetHashCode"
|
||||
|| methodName == "GetType"
|
||||
|| methodName == "ToString"
|
||||
|| methodName == "WithOptions"
|
||||
|| methodName == "WithHeaders"
|
||||
|| methodName == "WithDeadline"
|
||||
|| methodName == "WithCancellationToken"
|
||||
|| methodName == "WithHost"
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.Where(x => !x.IsSpecialName)
|
||||
.Select(x => new MethodDefinition
|
||||
{
|
||||
ServiceType = interfaceType,
|
||||
MethodInfo = x,
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
static void DefineStaticFields(TypeBuilder typeBuilder, MethodDefinition[] definitions)
|
||||
{
|
||||
foreach (var item in definitions)
|
||||
{
|
||||
item.FieldMethod = typeBuilder.DefineField(item.MethodInfo.Name + "Method", bytesMethod, FieldAttributes.Private | FieldAttributes.Static);
|
||||
item.ResponseType = UnwrapResponseType(item, out item.MethodType, out item.ResponseIsTask, out item.RequestType);
|
||||
|
||||
if (item.RequestType == null)
|
||||
{
|
||||
item.RequestType = MagicOnionMarshallers.CreateRequestType(item.MethodInfo.GetParameters());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DefineStaticConstructor(TypeBuilder typeBuilder, Type interfaceType, MethodDefinition[] definitions)
|
||||
{
|
||||
var cctor = typeBuilder.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes);
|
||||
var il = cctor.GetILGenerator();
|
||||
|
||||
for (int i = 0; i < definitions.Length; i++)
|
||||
{
|
||||
var def = definitions[i];
|
||||
|
||||
il.EmitLdc_I4((int)def.MethodType);
|
||||
il.Emit(OpCodes.Ldstr, def.ServiceType.Name);
|
||||
il.Emit(OpCodes.Ldstr, def.MethodInfo.Name);
|
||||
il.Emit(OpCodes.Ldsfld, throughMarshaller);
|
||||
il.Emit(OpCodes.Ldsfld, throughMarshaller);
|
||||
il.Emit(OpCodes.Newobj, bytesMethod.GetConstructors()[0]);
|
||||
il.Emit(OpCodes.Stsfld, def.FieldMethod);
|
||||
|
||||
if (def.MethodType == MethodType.Unary)
|
||||
{
|
||||
DefineUnaryRequestDelegate(il, typeBuilder, interfaceType, def);
|
||||
}
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
static void DefineUnaryRequestDelegate(ILGenerator staticContructorGenerator, TypeBuilder typeBuilder, Type interfaceType, MethodDefinition definition)
|
||||
{
|
||||
// static ResponseContext _Method(RequestContext context);
|
||||
MethodBuilder method;
|
||||
{
|
||||
method = typeBuilder.DefineMethod("_" + definition.MethodInfo.Name, MethodAttributes.Private | MethodAttributes.Static,
|
||||
typeof(ResponseContext),
|
||||
new[] { typeof(RequestContext) });
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
// CreateResponseContext<TRequest, TResponse>(Context, Method);
|
||||
var createMethod = typeof(MagicOnionClientBase)
|
||||
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
|
||||
.Where(x => x.Name == "CreateResponseContext")
|
||||
.OrderByDescending(x => x.GetGenericArguments().Length)
|
||||
.First()
|
||||
.MakeGenericMethod(definition.RequestType, definition.ResponseType);
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0); // context
|
||||
il.Emit(OpCodes.Ldsfld, definition.FieldMethod); // method
|
||||
il.Emit(OpCodes.Call, createMethod);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
// static readonly Func<RequestContext, ResposneContext> methodDelegate = _Method;
|
||||
{
|
||||
definition.UnaryRequestDelegate = typeBuilder.DefineField(definition.MethodInfo.Name + "Delegate", typeof(Func<RequestContext, ResponseContext>), FieldAttributes.Private | FieldAttributes.Static);
|
||||
|
||||
var il = staticContructorGenerator;
|
||||
il.Emit(OpCodes.Ldnull);
|
||||
il.Emit(OpCodes.Ldftn, method);
|
||||
il.Emit(OpCodes.Newobj, typeof(Func<RequestContext, ResponseContext>).GetConstructors()[0]);
|
||||
il.Emit(OpCodes.Stsfld, definition.UnaryRequestDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
static ConstructorInfo DefineConstructors(TypeBuilder typeBuilder, MethodDefinition[] definitions)
|
||||
{
|
||||
ConstructorInfo emptyCtor;
|
||||
// .ctor()
|
||||
{
|
||||
var ctor = typeBuilder.DefineConstructor(MethodAttributes.Private, CallingConventions.Standard, Type.EmptyTypes);
|
||||
var il = ctor.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, typeBuilder.BaseType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null));
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
emptyCtor = ctor;
|
||||
}
|
||||
|
||||
// .ctor(CallInvoker, MessagePackSerializerOptions, IClientFilter[]):base(callInvoker, resolver, clientFilters)
|
||||
{
|
||||
var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(CallInvoker), typeof(MessagePackSerializerOptions), typeof(IClientFilter[]) });
|
||||
var il = ctor.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
il.Emit(OpCodes.Ldarg_3);
|
||||
il.Emit(OpCodes.Call, typeBuilder.BaseType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(CallInvoker), typeof(MessagePackSerializerOptions), typeof(IClientFilter[]) }, null));
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
return emptyCtor;
|
||||
}
|
||||
|
||||
static void DefineMethods(TypeBuilder typeBuilder, Type interfaceType, MethodDefinition[] definitions, ConstructorInfo emptyCtor)
|
||||
{
|
||||
var filedHolderType = typeof(MagicOnionClientBase);
|
||||
var baseType = typeof(MagicOnionClientBase<>).MakeGenericType(interfaceType);
|
||||
var hostField = filedHolderType.GetField("host", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var optionField = filedHolderType.GetField("option", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var invokerField = filedHolderType.GetField("callInvoker", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var serializerOptionsField = filedHolderType.GetField("serializerOptions", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var filtersField = filedHolderType.GetField("filters", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
// Clone
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("Clone", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
typeof(MagicOnionClientBase<>).MakeGenericType(interfaceType),
|
||||
Type.EmptyTypes);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Newobj, emptyCtor);
|
||||
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, hostField);
|
||||
il.Emit(OpCodes.Stfld, hostField);
|
||||
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, optionField);
|
||||
il.Emit(OpCodes.Stfld, optionField);
|
||||
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, invokerField);
|
||||
il.Emit(OpCodes.Stfld, invokerField);
|
||||
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Stfld, serializerOptionsField);
|
||||
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, filtersField);
|
||||
il.Emit(OpCodes.Stfld, filtersField);
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
// Overrides
|
||||
{
|
||||
// TSelf WithOption(CallOptions option)
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("WithOptions", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
interfaceType,
|
||||
new[] { typeof(CallOptions) });
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Call, baseType.GetMethod("WithOptions", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
// TSelf WithHeaders(Metadata headers);
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("WithHeaders", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
interfaceType,
|
||||
new[] { typeof(Metadata) });
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Call, baseType.GetMethod("WithHeaders", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
// TSelf WithDeadline(DateTime deadline);
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("WithDeadline", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
interfaceType,
|
||||
new[] { typeof(DateTime) });
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Call, baseType.GetMethod("WithDeadline", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
// TSelf WithCancellationToken(CancellationToken cancellationToken);
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("WithCancellationToken", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
interfaceType,
|
||||
new[] { typeof(CancellationToken) });
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Call, baseType.GetMethod("WithCancellationToken", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
// TSelf WithHost(string host);
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("WithHost", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
interfaceType,
|
||||
new[] { typeof(string) });
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Call, baseType.GetMethod("WithHost", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
// Proxy Methods
|
||||
for (int i = 0; i < definitions.Length; i++)
|
||||
{
|
||||
var def = definitions[i];
|
||||
var parameters = def.MethodInfo.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||
|
||||
var method = typeBuilder.DefineMethod(def.MethodInfo.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
def.MethodInfo.ReturnType,
|
||||
parameters);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
switch (def.MethodType)
|
||||
{
|
||||
case MethodType.Unary:
|
||||
{
|
||||
// base.InvokeAsync<TRequest, TResponse>/InvokeTaskAsync(string path, TRequest request, Func<RequestContext, ResponseContext> requestMethod)
|
||||
|
||||
// this.
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
|
||||
// path
|
||||
il.Emit(OpCodes.Ldstr, def.Path);
|
||||
|
||||
// create request
|
||||
for (int j = 0; j < parameters.Length; j++)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg, j + 1);
|
||||
}
|
||||
if (parameters.Length == 0)
|
||||
{
|
||||
// use empty byte[0]
|
||||
il.Emit(OpCodes.Ldsfld, nilBytes);
|
||||
}
|
||||
else if (parameters.Length == 1)
|
||||
{
|
||||
// already loaded parameter.
|
||||
}
|
||||
else
|
||||
{
|
||||
// call new DynamicArgumentTuple<T>
|
||||
il.Emit(OpCodes.Newobj, def.RequestType.GetConstructors()[0]);
|
||||
}
|
||||
|
||||
// requestMethod
|
||||
il.Emit(OpCodes.Ldsfld, def.UnaryRequestDelegate);
|
||||
|
||||
// InvokeAsync/InvokeTaskAsync
|
||||
var invokeMethod = def.ResponseIsTask
|
||||
? baseType.GetMethod("InvokeTaskAsync", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance)
|
||||
: baseType.GetMethod("InvokeAsync", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance);
|
||||
invokeMethod = invokeMethod.MakeGenericMethod(def.RequestType, def.ResponseType);
|
||||
il.Emit(OpCodes.Callvirt, invokeMethod);
|
||||
}
|
||||
|
||||
break;
|
||||
case MethodType.ServerStreaming:
|
||||
{
|
||||
il.DeclareLocal(typeof(byte[])); // request
|
||||
il.DeclareLocal(typeof(AsyncServerStreamingCall<byte[]>));
|
||||
|
||||
// create request
|
||||
for (int j = 0; j < parameters.Length; j++)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg, j + 1);
|
||||
}
|
||||
if (parameters.Length == 0)
|
||||
{
|
||||
// use empty byte[0]
|
||||
il.Emit(OpCodes.Ldsfld, nilBytes);
|
||||
}
|
||||
else if (parameters.Length == 1)
|
||||
{
|
||||
// already loaded parameter.
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Call, callCancellationTokenNone);
|
||||
il.Emit(OpCodes.Call, callMessagePackSerialize.MakeGenericMethod(def.RequestType));
|
||||
}
|
||||
else
|
||||
{
|
||||
// call new DynamicArgumentTuple<T>
|
||||
il.Emit(OpCodes.Newobj, def.RequestType.GetConstructors()[0]);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Call, callCancellationTokenNone);
|
||||
il.Emit(OpCodes.Call, callMessagePackSerialize.MakeGenericMethod(def.RequestType));
|
||||
}
|
||||
il.Emit(OpCodes.Stloc_0);
|
||||
|
||||
// create ***Result
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, invokerField);
|
||||
il.Emit(OpCodes.Ldsfld, def.FieldMethod);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, hostField);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, optionField);
|
||||
il.Emit(OpCodes.Ldloc_0);
|
||||
il.Emit(OpCodes.Callvirt, typeof(CallInvoker).GetMethod("AsyncServerStreamingCall").MakeGenericMethod(typeof(byte[]), typeof(byte[])));
|
||||
il.Emit(OpCodes.Stloc_1);
|
||||
|
||||
// create return result
|
||||
// new ServerStreamingResult<TResponse>(
|
||||
|
||||
// inner,
|
||||
il.Emit(OpCodes.Ldloc_1);
|
||||
|
||||
// new MarshallingAsyncStreamReader<TResponse>(inner.ResponseStream, this.resolver),
|
||||
il.Emit(OpCodes.Ldloc_1);
|
||||
il.Emit(OpCodes.Call, typeof(AsyncServerStreamingCall<byte[]>).GetProperty("ResponseStream").GetMethod);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Newobj, typeof(MarshallingAsyncStreamReader<>).MakeGenericType(def.ResponseType).GetConstructors().Single());
|
||||
|
||||
// this.resolver
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
|
||||
// );
|
||||
|
||||
var resultType = typeof(ServerStreamingResult<>).MakeGenericType(def.ResponseType);
|
||||
il.Emit(OpCodes.Newobj, resultType.GetConstructors()[0]);
|
||||
if (def.ResponseIsTask)
|
||||
{
|
||||
il.Emit(OpCodes.Call, typeof(Task).GetMethod("FromResult").MakeGenericMethod(resultType));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MethodType.ClientStreaming:
|
||||
case MethodType.DuplexStreaming:
|
||||
if (def.MethodType == MethodType.ClientStreaming)
|
||||
{
|
||||
il.DeclareLocal(typeof(AsyncClientStreamingCall<byte[], byte[]>)); // callResult
|
||||
}
|
||||
else
|
||||
{
|
||||
il.DeclareLocal(typeof(AsyncDuplexStreamingCall<byte[], byte[]>)); // callResult
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, invokerField);
|
||||
il.Emit(OpCodes.Ldsfld, def.FieldMethod);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, hostField);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, optionField);
|
||||
if (def.MethodType == MethodType.ClientStreaming)
|
||||
{
|
||||
il.Emit(OpCodes.Callvirt, typeof(CallInvoker).GetMethod("AsyncClientStreamingCall").MakeGenericMethod(typeof(byte[]), typeof(byte[])));
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Callvirt, typeof(CallInvoker).GetMethod("AsyncDuplexStreamingCall").MakeGenericMethod(typeof(byte[]), typeof(byte[])));
|
||||
}
|
||||
il.Emit(OpCodes.Stloc_0);
|
||||
|
||||
// create return result
|
||||
Type resultType2;
|
||||
if (def.MethodType == MethodType.ClientStreaming)
|
||||
{
|
||||
// new ClientStreamingResult<TRequest, TResponse>(
|
||||
// inner,
|
||||
il.Emit(OpCodes.Ldloc_0);
|
||||
|
||||
// new MarshallingClientStreamWriter<TRequest>()(inner.RequestStream, this.resolver),
|
||||
il.Emit(OpCodes.Ldloc_0);
|
||||
il.Emit(OpCodes.Call, typeof(AsyncClientStreamingCall<byte[], byte[]>).GetProperty("RequestStream").GetMethod);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Newobj, (typeof(MarshallingClientStreamWriter<>).MakeGenericType(def.RequestType).GetConstructors().Single()));
|
||||
|
||||
// this.resolver
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
|
||||
// );
|
||||
resultType2 = typeof(ClientStreamingResult<,>).MakeGenericType(def.RequestType, def.ResponseType);
|
||||
il.Emit(OpCodes.Newobj, resultType2.GetConstructors().OrderBy(x => x.GetParameters().Length).Last());
|
||||
}
|
||||
else
|
||||
{
|
||||
// new DuplexStreamingResult<TRequest, TResponse>(
|
||||
// inner,
|
||||
il.Emit(OpCodes.Ldloc_0);
|
||||
|
||||
// new MarshallingClientStreamWriter<TRequest>()(inner.RequestStream, this.resolver),
|
||||
il.Emit(OpCodes.Ldloc_0);
|
||||
il.Emit(OpCodes.Call, typeof(AsyncDuplexStreamingCall<byte[], byte[]>).GetProperty("RequestStream").GetMethod);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Newobj, (typeof(MarshallingClientStreamWriter<>).MakeGenericType(def.RequestType).GetConstructors().Single()));
|
||||
|
||||
// new MarshallingAsyncStreamReader<TResponse>()(inner.ResponseStream, this.resolver),
|
||||
il.Emit(OpCodes.Ldloc_0);
|
||||
il.Emit(OpCodes.Call, typeof(AsyncDuplexStreamingCall<byte[], byte[]>).GetProperty("ResponseStream").GetMethod);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Newobj, (typeof(MarshallingAsyncStreamReader<>).MakeGenericType(def.ResponseType).GetConstructors().Single()));
|
||||
|
||||
// this.resolver
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
|
||||
// );
|
||||
resultType2 = typeof(DuplexStreamingResult<,>).MakeGenericType(def.RequestType, def.ResponseType);
|
||||
il.Emit(OpCodes.Newobj, resultType2.GetConstructors()[0]);
|
||||
}
|
||||
|
||||
if (def.ResponseIsTask)
|
||||
{
|
||||
il.Emit(OpCodes.Call, typeof(Task).GetMethod("FromResult").MakeGenericMethod(resultType2));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Not supported method type:" + def.MethodType);
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
|
||||
static Type UnwrapResponseType(MethodDefinition def, out MethodType methodType, out bool responseIsTask, out Type requestTypeIfExists)
|
||||
{
|
||||
//if (!t.IsGenericType) throw new Exception($"Invalid ResponseType, Path:{def.Path} Type:{t.Name}");
|
||||
|
||||
var t = def.MethodInfo.ReturnType;
|
||||
if (!t.GetTypeInfo().IsGenericType) throw new Exception($"Invalid return type, path:{def.Path} type:{t.Name}");
|
||||
|
||||
// Task<Unary<T>>
|
||||
if (t.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
{
|
||||
responseIsTask = true;
|
||||
t = t.GetGenericArguments()[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
responseIsTask = false;
|
||||
}
|
||||
|
||||
// Unary<T>
|
||||
var returnType = t.GetGenericTypeDefinition();
|
||||
if (returnType == typeof(UnaryResult<>))
|
||||
{
|
||||
methodType = MethodType.Unary;
|
||||
requestTypeIfExists = null;
|
||||
return t.GetGenericArguments()[0];
|
||||
}
|
||||
else if (returnType == typeof(ClientStreamingResult<,>))
|
||||
{
|
||||
methodType = MethodType.ClientStreaming;
|
||||
var genArgs = t.GetGenericArguments();
|
||||
requestTypeIfExists = genArgs[0];
|
||||
return genArgs[1];
|
||||
}
|
||||
else if (returnType == typeof(ServerStreamingResult<>))
|
||||
{
|
||||
methodType = MethodType.ServerStreaming;
|
||||
requestTypeIfExists = null;
|
||||
return t.GetGenericArguments()[0];
|
||||
}
|
||||
else if (returnType == typeof(DuplexStreamingResult<,>))
|
||||
{
|
||||
methodType = MethodType.DuplexStreaming;
|
||||
var genArgs = t.GetGenericArguments();
|
||||
requestTypeIfExists = genArgs[0];
|
||||
return genArgs[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Invalid return type, path:{def.Path} type:{t.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
class MethodDefinition
|
||||
{
|
||||
public string Path => ServiceType.Name + "/" + MethodInfo.Name;
|
||||
|
||||
// set after search definitions
|
||||
public Type ServiceType;
|
||||
public MethodInfo MethodInfo;
|
||||
public MethodType MethodType;
|
||||
|
||||
// set after define static fields
|
||||
public bool ResponseIsTask;
|
||||
public FieldInfo FieldMethod;
|
||||
public Type RequestType;
|
||||
public Type ResponseType;
|
||||
|
||||
// unary only, set after define static fields
|
||||
public FieldInfo UnaryRequestDelegate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4756b0967dbdbae4fb4cb2afb87f4101
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
internal static class InterceptInvokeHelper
|
||||
{
|
||||
public static ValueTask<ResponseContext> InvokeWithFilter(RequestContext context)
|
||||
{
|
||||
switch (context.Filters.Length)
|
||||
{
|
||||
case 0:
|
||||
return new ValueTask<ResponseContext>(context.RequestMethod(context));
|
||||
case 1:
|
||||
return InvokeWithFilter1(context);
|
||||
case 2:
|
||||
return InvokeWithFilter2(context);
|
||||
case 3:
|
||||
return InvokeWithFilter3(context);
|
||||
case 4:
|
||||
return InvokeWithFilter4(context);
|
||||
case 5:
|
||||
return InvokeWithFilter5(context);
|
||||
case 6:
|
||||
return InvokeWithFilter6(context);
|
||||
case 7:
|
||||
return InvokeWithFilter7(context);
|
||||
case 8:
|
||||
return InvokeWithFilter8(context);
|
||||
case 9:
|
||||
return InvokeWithFilter9(context);
|
||||
case 10:
|
||||
return InvokeWithFilter10(context);
|
||||
default:
|
||||
return InvokeRecursive(-1, context);
|
||||
}
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter1(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync()));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter2(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync())));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter3(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
x2 => x2.Filters[2].SendAsync(x2,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync()))));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter4(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
x2 => x2.Filters[2].SendAsync(x2,
|
||||
x3 => x3.Filters[3].SendAsync(x3,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync())))));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter5(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
x2 => x2.Filters[2].SendAsync(x2,
|
||||
x3 => x3.Filters[3].SendAsync(x3,
|
||||
x4 => x4.Filters[4].SendAsync(x4,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync()))))));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter6(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
x2 => x2.Filters[2].SendAsync(x2,
|
||||
x3 => x3.Filters[3].SendAsync(x3,
|
||||
x4 => x4.Filters[4].SendAsync(x4,
|
||||
x5 => x5.Filters[5].SendAsync(x5,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync())))))));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter7(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
x2 => x2.Filters[2].SendAsync(x2,
|
||||
x3 => x3.Filters[3].SendAsync(x3,
|
||||
x4 => x4.Filters[4].SendAsync(x4,
|
||||
x5 => x5.Filters[5].SendAsync(x5,
|
||||
x6 => x6.Filters[6].SendAsync(x6,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync()))))))));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter8(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
x2 => x2.Filters[2].SendAsync(x2,
|
||||
x3 => x3.Filters[3].SendAsync(x3,
|
||||
x4 => x4.Filters[4].SendAsync(x4,
|
||||
x5 => x5.Filters[5].SendAsync(x5,
|
||||
x6 => x6.Filters[6].SendAsync(x6,
|
||||
x7 => x7.Filters[7].SendAsync(x7,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync())))))))));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter9(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
x2 => x2.Filters[2].SendAsync(x2,
|
||||
x3 => x3.Filters[3].SendAsync(x3,
|
||||
x4 => x4.Filters[4].SendAsync(x4,
|
||||
x5 => x5.Filters[5].SendAsync(x5,
|
||||
x6 => x6.Filters[6].SendAsync(x6,
|
||||
x7 => x7.Filters[7].SendAsync(x7,
|
||||
x8 => x8.Filters[8].SendAsync(x8,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync()))))))))));
|
||||
}
|
||||
|
||||
static ValueTask<ResponseContext> InvokeWithFilter10(RequestContext context)
|
||||
{
|
||||
return context.Filters[0].SendAsync(context,
|
||||
x1 => x1.Filters[1].SendAsync(x1,
|
||||
x2 => x2.Filters[2].SendAsync(x2,
|
||||
x3 => x3.Filters[3].SendAsync(x3,
|
||||
x4 => x4.Filters[4].SendAsync(x4,
|
||||
x5 => x5.Filters[5].SendAsync(x5,
|
||||
x6 => x6.Filters[6].SendAsync(x6,
|
||||
x7 => x7.Filters[7].SendAsync(x7,
|
||||
x8 => x8.Filters[8].SendAsync(x8,
|
||||
x9 => x9.Filters[9].SendAsync(x9,
|
||||
ctx => new ValueTask<ResponseContext>(ctx.RequestMethod(ctx).WaitResponseAsync())))))))))));
|
||||
}
|
||||
|
||||
// for invoke N filters(slow path).
|
||||
|
||||
static ValueTask<ResponseContext> InvokeRecursive(int index, RequestContext context)
|
||||
{
|
||||
index += 1; // start from -1
|
||||
if (index != context.Filters.Length)
|
||||
{
|
||||
return context.Filters[index].SendAsync(context, ctx => InvokeRecursive(index, ctx));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ValueTask<ResponseContext>(context.RequestMethod(context).WaitResponseAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4a428b894e3ddac4a80496efd076633c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
using System;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
public static class MagicOnionClient
|
||||
{
|
||||
static readonly IClientFilter[] emptyFilters = Array.Empty<IClientFilter>();
|
||||
|
||||
public static T Create<T>(Channel channel)
|
||||
where T : IService<T>
|
||||
{
|
||||
return Create<T>(new DefaultCallInvoker(channel), MessagePackSerializer.DefaultOptions, emptyFilters);
|
||||
}
|
||||
|
||||
public static T Create<T>(CallInvoker invoker)
|
||||
where T : IService<T>
|
||||
{
|
||||
return Create<T>(invoker, MessagePackSerializer.DefaultOptions, emptyFilters);
|
||||
}
|
||||
|
||||
public static T Create<T>(Channel channel, IClientFilter[] clientFilters)
|
||||
where T : IService<T>
|
||||
{
|
||||
return Create<T>(new DefaultCallInvoker(channel), MessagePackSerializer.DefaultOptions, clientFilters);
|
||||
}
|
||||
|
||||
public static T Create<T>(CallInvoker invoker, IClientFilter[] clientFilters)
|
||||
where T : IService<T>
|
||||
{
|
||||
return Create<T>(invoker, MessagePackSerializer.DefaultOptions, clientFilters);
|
||||
}
|
||||
|
||||
public static T Create<T>(Channel channel, MessagePackSerializerOptions serializerOptions)
|
||||
where T : IService<T>
|
||||
{
|
||||
return Create<T>(new DefaultCallInvoker(channel), serializerOptions, emptyFilters);
|
||||
}
|
||||
|
||||
public static T Create<T>(CallInvoker invoker, MessagePackSerializerOptions serializerOptions)
|
||||
where T : IService<T>
|
||||
{
|
||||
return Create<T>(invoker, serializerOptions, emptyFilters);
|
||||
}
|
||||
|
||||
public static T Create<T>(CallInvoker invoker, MessagePackSerializerOptions serializerOptions, IClientFilter[] clientFilters)
|
||||
where T : IService<T>
|
||||
{
|
||||
if (invoker == null) throw new ArgumentNullException(nameof(invoker));
|
||||
|
||||
var ctor = MagicOnionClientRegistry<T>.consturtor;
|
||||
if (ctor == null)
|
||||
{
|
||||
#if ((ENABLE_IL2CPP && !UNITY_EDITOR) || NET_STANDARD_2_0)
|
||||
throw new InvalidOperationException("Does not registered client factory, dynamic code generation is not supported on IL2CPP. Please use code generator(moc).");
|
||||
#else
|
||||
var t = DynamicClientBuilder<T>.ClientType;
|
||||
return (T)Activator.CreateInstance(t, invoker, serializerOptions, clientFilters);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return ctor(invoker, serializerOptions, clientFilters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MagicOnionClientRegistry<T>
|
||||
where T : IService<T>
|
||||
{
|
||||
public static Func<CallInvoker, MessagePackSerializerOptions, IClientFilter[], T> consturtor;
|
||||
|
||||
public static void Register(Func<CallInvoker, MessagePackSerializerOptions, IClientFilter[], T> ctor)
|
||||
{
|
||||
consturtor = ctor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5cd0a981f86ef1843bf6b375b2d9b5dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
public abstract class MagicOnionClientBase
|
||||
{
|
||||
protected string host;
|
||||
protected CallOptions option;
|
||||
protected CallInvoker callInvoker;
|
||||
protected MessagePackSerializerOptions serializerOptions;
|
||||
protected IClientFilter[] filters;
|
||||
|
||||
static protected ResponseContext CreateResponseContext<TResponse>(RequestContext context, Method<byte[], byte[]> method)
|
||||
{
|
||||
var self = context.Client;
|
||||
var callResult = self.callInvoker.AsyncUnaryCall(method, self.host, context.CallOptions, context.RequestMutator(MagicOnionMarshallers.UnsafeNilBytes));
|
||||
var response = new ResponseContext<TResponse>(callResult, self.serializerOptions);
|
||||
response.SetResponseMutator(context.ResponseMutator);
|
||||
return response;
|
||||
}
|
||||
|
||||
static protected ResponseContext CreateResponseContext<TRequest, TResponse>(RequestContext context, Method<byte[], byte[]> method)
|
||||
{
|
||||
var self = context.Client;
|
||||
var message = MessagePackSerializer.Serialize<TRequest>(((RequestContext<TRequest>)context).Request, self.serializerOptions);
|
||||
var callResult = self.callInvoker.AsyncUnaryCall(method, self.host, context.CallOptions, context.RequestMutator(message));
|
||||
var response = new ResponseContext<TResponse>(callResult, self.serializerOptions);
|
||||
response.SetResponseMutator(context.ResponseMutator);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class MagicOnionClientBase<T> : MagicOnionClientBase
|
||||
where T : IService<T>
|
||||
{
|
||||
protected MagicOnionClientBase()
|
||||
{
|
||||
}
|
||||
|
||||
protected MagicOnionClientBase(CallInvoker callInvoker, MessagePackSerializerOptions serializerOptions, IClientFilter[] filters)
|
||||
{
|
||||
this.callInvoker = callInvoker;
|
||||
this.serializerOptions = serializerOptions;
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
protected UnaryResult<TResponse> InvokeAsync<TRequest, TResponse>(string path, TRequest request, Func<RequestContext, ResponseContext> requestMethod)
|
||||
{
|
||||
var future = InvokeAsyncCore<TRequest, TResponse>(path, request, requestMethod);
|
||||
return new UnaryResult<TResponse>(future);
|
||||
}
|
||||
|
||||
async Task<IResponseContext<TResponse>> InvokeAsyncCore<TRequest, TResponse>(string path, TRequest request, Func<RequestContext, ResponseContext> requestMethod)
|
||||
{
|
||||
if (this.option.Headers == null && filters.Length != 0)
|
||||
{
|
||||
// always creating new Metadata is bad manner for performance
|
||||
this.option = this.option.WithHeaders(new Metadata());
|
||||
}
|
||||
|
||||
var requestContext = new RequestContext<TRequest>(request, this, path, option, typeof(TResponse), filters, requestMethod);
|
||||
var response = await InterceptInvokeHelper.InvokeWithFilter(requestContext);
|
||||
var result = response as IResponseContext<TResponse>;
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("ResponseContext is null.");
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task<UnaryResult<TResponse>> InvokeTaskAsync<TRequest, TResponse>(string path, TRequest request, Func<RequestContext, ResponseContext> requestMethod)
|
||||
{
|
||||
if (this.option.Headers == null && filters.Length != 0)
|
||||
{
|
||||
// always creating new Metadata is bad manner for performance
|
||||
this.option = this.option.WithHeaders(new Metadata());
|
||||
}
|
||||
|
||||
var requestContext = new RequestContext<TRequest>(request, this, path, option, typeof(TResponse), filters, requestMethod);
|
||||
var response = await InterceptInvokeHelper.InvokeWithFilter(requestContext);
|
||||
var result = response as IResponseContext<TResponse>;
|
||||
if (result != null)
|
||||
{
|
||||
return new UnaryResult<TResponse>(Task.FromResult(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("ResponseContext is null.");
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract MagicOnionClientBase<T> Clone();
|
||||
|
||||
public virtual T WithCancellationToken(CancellationToken cancellationToken)
|
||||
{
|
||||
return WithOptions(this.option.WithCancellationToken(cancellationToken));
|
||||
}
|
||||
|
||||
public virtual T WithDeadline(DateTime deadline)
|
||||
{
|
||||
return WithOptions(this.option.WithDeadline(deadline));
|
||||
}
|
||||
|
||||
public virtual T WithHeaders(Metadata headers)
|
||||
{
|
||||
return WithOptions(this.option.WithHeaders(headers));
|
||||
}
|
||||
|
||||
public virtual T WithHost(string host)
|
||||
{
|
||||
var newInstance = Clone();
|
||||
newInstance.host = host;
|
||||
return (T)(object)newInstance;
|
||||
}
|
||||
|
||||
public virtual T WithOptions(CallOptions option)
|
||||
{
|
||||
var newInstance = Clone();
|
||||
newInstance.option = option;
|
||||
return (T)(object)newInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d469b4f1a615e4f4f8bf51459e9e5d50
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using Grpc.Core.Logging;
|
||||
using MessagePack;
|
||||
using System;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
public static class StreamingHubClient
|
||||
{
|
||||
public static TStreamingHub Connect<TStreamingHub, TReceiver>(Channel channel, TReceiver receiver, string host = null, CallOptions option = default(CallOptions), MessagePackSerializerOptions serializerOptions = null, ILogger logger = null)
|
||||
where TStreamingHub : IStreamingHub<TStreamingHub, TReceiver>
|
||||
{
|
||||
return Connect<TStreamingHub, TReceiver>(new DefaultCallInvoker(channel), receiver, host, option, serializerOptions, logger);
|
||||
}
|
||||
|
||||
public static TStreamingHub Connect<TStreamingHub, TReceiver>(CallInvoker callInvoker, TReceiver receiver, string host = null, CallOptions option = default(CallOptions), MessagePackSerializerOptions serializerOptions = null, ILogger logger = null)
|
||||
where TStreamingHub : IStreamingHub<TStreamingHub, TReceiver>
|
||||
{
|
||||
var ctor = StreamingHubClientRegistry<TStreamingHub, TReceiver>.consturtor;
|
||||
StreamingHubClientBase<TStreamingHub, TReceiver> client = null;
|
||||
if (ctor == null)
|
||||
{
|
||||
#if ((ENABLE_IL2CPP && !UNITY_EDITOR) || NET_STANDARD_2_0)
|
||||
throw new InvalidOperationException("Does not registered client factory, dynamic code generation is not supported on IL2CPP. Please use code generator(moc).");
|
||||
#else
|
||||
var type = StreamingHubClientBuilder<TStreamingHub, TReceiver>.ClientType;
|
||||
client = (StreamingHubClientBase<TStreamingHub, TReceiver>)Activator.CreateInstance(type, new object[] { callInvoker, host, option, serializerOptions, logger });
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
client = (StreamingHubClientBase<TStreamingHub, TReceiver>)(object)ctor(callInvoker, receiver, host, option, serializerOptions, logger);
|
||||
}
|
||||
|
||||
client.__ConnectAndSubscribe(receiver);
|
||||
return (TStreamingHub)(object)client;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StreamingHubClientRegistry<TStreamingHub, TReceiver>
|
||||
where TStreamingHub : IStreamingHub<TStreamingHub, TReceiver>
|
||||
{
|
||||
public static Func<CallInvoker, TReceiver, string, CallOptions, MessagePackSerializerOptions, ILogger, TStreamingHub> consturtor;
|
||||
|
||||
public static void Register(Func<CallInvoker, TReceiver, string, CallOptions, MessagePackSerializerOptions, ILogger, TStreamingHub> ctor)
|
||||
{
|
||||
consturtor = ctor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d74d1bafd22f5794fa60ad8963e9be64
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,332 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using Grpc.Core.Logging;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using MagicOnion.Utils;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MagicOnion.Server;
|
||||
using System.Buffers;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
public abstract class StreamingHubClientBase<TStreamingHub, TReceiver>
|
||||
where TStreamingHub : IStreamingHub<TStreamingHub, TReceiver>
|
||||
{
|
||||
readonly string host;
|
||||
readonly CallOptions option;
|
||||
readonly CallInvoker callInvoker;
|
||||
readonly ILogger logger;
|
||||
|
||||
protected readonly MessagePackSerializerOptions serializerOptions;
|
||||
readonly AsyncLock asyncLock = new AsyncLock();
|
||||
|
||||
DuplexStreamingResult<byte[], byte[]> connection;
|
||||
protected TReceiver receiver;
|
||||
Task subscription;
|
||||
TaskCompletionSource<object> waitForDisconnect = new TaskCompletionSource<object>();
|
||||
|
||||
// {messageId, TaskCompletionSource}
|
||||
ConcurrentDictionary<int, object> responseFutures = new ConcurrentDictionary<int, object>();
|
||||
protected CancellationTokenSource cts = new CancellationTokenSource();
|
||||
int messageId = 0;
|
||||
bool disposed;
|
||||
|
||||
protected StreamingHubClientBase(CallInvoker callInvoker, string host, CallOptions option, MessagePackSerializerOptions serializerOptions, ILogger logger)
|
||||
{
|
||||
this.callInvoker = callInvoker;
|
||||
this.host = host;
|
||||
this.option = option;
|
||||
this.serializerOptions = serializerOptions;
|
||||
this.logger = logger ?? GrpcEnvironment.Logger;
|
||||
}
|
||||
|
||||
protected abstract Method<byte[], byte[]> DuplexStreamingAsyncMethod { get; }
|
||||
|
||||
// call immediately after create.
|
||||
public void __ConnectAndSubscribe(TReceiver receiver)
|
||||
{
|
||||
var callResult = callInvoker.AsyncDuplexStreamingCall<byte[], byte[]>(DuplexStreamingAsyncMethod, host, option);
|
||||
var streamingResult = new DuplexStreamingResult<byte[], byte[]>(
|
||||
callResult,
|
||||
new MarshallingClientStreamWriter<byte[]>(callResult.RequestStream, serializerOptions),
|
||||
new MarshallingAsyncStreamReader<byte[]>(callResult.ResponseStream, serializerOptions),
|
||||
serializerOptions
|
||||
);
|
||||
|
||||
this.connection = streamingResult;
|
||||
this.receiver = receiver;
|
||||
this.subscription = StartSubscribe();
|
||||
}
|
||||
|
||||
protected abstract void OnResponseEvent(int methodId, object taskCompletionSource, ArraySegment<byte> data);
|
||||
protected abstract void OnBroadcastEvent(int methodId, ArraySegment<byte> data);
|
||||
|
||||
async Task StartSubscribe()
|
||||
{
|
||||
var syncContext = SynchronizationContext.Current; // capture SynchronizationContext.
|
||||
var reader = connection.RawStreamingCall.ResponseStream;
|
||||
try
|
||||
{
|
||||
while (await reader.MoveNext(cts.Token).ConfigureAwait(false)) // avoid Post to SyncContext(it losts one-frame per operation)
|
||||
{
|
||||
try
|
||||
{
|
||||
// MessageFormat:
|
||||
// broadcast: [methodId, [argument]]
|
||||
// response: [messageId, methodId, response]
|
||||
// error-response: [messageId, statusCode, detail, StringMessage]
|
||||
void ConsumeData(byte[] data)
|
||||
{
|
||||
var messagePackReader = new MessagePackReader(data);
|
||||
var arrayLength = messagePackReader.ReadArrayHeader();
|
||||
if (arrayLength == 3)
|
||||
{
|
||||
var messageId = messagePackReader.ReadInt32();
|
||||
object future;
|
||||
if (responseFutures.TryRemove(messageId, out future))
|
||||
{
|
||||
var methodId = messagePackReader.ReadInt32();
|
||||
try
|
||||
{
|
||||
var offset = (int)messagePackReader.Consumed;
|
||||
var rest = new ArraySegment<byte>(data, offset, data.Length - offset);
|
||||
OnResponseEvent(methodId, future, rest);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!(future as ITaskCompletion).TrySetException(ex))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (arrayLength == 4)
|
||||
{
|
||||
var messageId = messagePackReader.ReadInt32();
|
||||
object future;
|
||||
if (responseFutures.TryRemove(messageId, out future))
|
||||
{
|
||||
var statusCode = messagePackReader.ReadInt32();
|
||||
var detail = messagePackReader.ReadString();
|
||||
var offset = (int)messagePackReader.Consumed;
|
||||
var rest = new ArraySegment<byte>(data, offset, data.Length - offset);
|
||||
var error = MessagePackSerializer.Deserialize<string>(rest, serializerOptions);
|
||||
(future as ITaskCompletion).TrySetException(new RpcException(new Status((StatusCode)statusCode, detail), error));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var methodId = messagePackReader.ReadInt32();
|
||||
var offset = (int)messagePackReader.Consumed;
|
||||
if (syncContext != null)
|
||||
{
|
||||
var tuple = Tuple.Create(methodId, data, offset, data.Length - offset);
|
||||
syncContext.Post(state =>
|
||||
{
|
||||
var t = (Tuple<int, byte[], int, int>)state;
|
||||
OnBroadcastEvent(t.Item1, new ArraySegment<byte>(t.Item2, t.Item3, t.Item4));
|
||||
}, tuple);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnBroadcastEvent(methodId, new ArraySegment<byte>(data, offset, data.Length - offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConsumeData(reader.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
const string msg = "Error on consume received message, but keep subscribe.";
|
||||
// log post on main thread.
|
||||
if (syncContext != null)
|
||||
{
|
||||
syncContext.Post(state => logger.Error((Exception)state, msg), ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error(ex, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is OperationCanceledException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const string msg = "Error on subscribing message.";
|
||||
// log post on main thread.
|
||||
if (syncContext != null)
|
||||
{
|
||||
syncContext.Post(state => logger.Error((Exception)state, msg), ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error(ex, msg);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
// set syncContext before await
|
||||
if (syncContext != null && SynchronizationContext.Current == null)
|
||||
{
|
||||
SynchronizationContext.SetSynchronizationContext(syncContext);
|
||||
}
|
||||
await DisposeAsyncCore(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
waitForDisconnect.TrySetResult(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected async Task WriteMessageAsync<T>(int methodId, T message)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
byte[] BuildMessage()
|
||||
{
|
||||
using (var buffer = ArrayPoolBufferWriter.RentThreadStaticWriter())
|
||||
{
|
||||
var writer = new MessagePackWriter(buffer);
|
||||
writer.WriteArrayHeader(2);
|
||||
writer.Write(methodId);
|
||||
MessagePackSerializer.Serialize(ref writer, message, serializerOptions);
|
||||
writer.Flush();
|
||||
return buffer.WrittenSpan.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
var v = BuildMessage();
|
||||
using (await asyncLock.LockAsync())
|
||||
{
|
||||
await connection.RawStreamingCall.RequestStream.WriteAsync(v).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task<TResponse> WriteMessageAsyncFireAndForget<TRequest, TResponse>(int methodId, TRequest message)
|
||||
{
|
||||
await WriteMessageAsync(methodId, message).ConfigureAwait(false);
|
||||
return default(TResponse);
|
||||
}
|
||||
|
||||
protected async Task<TResponse> WriteMessageWithResponseAsync<TRequest, TResponse>(int methodId, TRequest message)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
var mid = Interlocked.Increment(ref messageId);
|
||||
var tcs = new TaskCompletionSourceEx<TResponse>(); // use Ex
|
||||
responseFutures[mid] = (object)tcs;
|
||||
|
||||
byte[] BuildMessage()
|
||||
{
|
||||
using (var buffer = ArrayPoolBufferWriter.RentThreadStaticWriter())
|
||||
{
|
||||
var writer = new MessagePackWriter(buffer);
|
||||
writer.WriteArrayHeader(3);
|
||||
writer.Write(mid);
|
||||
writer.Write(methodId);
|
||||
MessagePackSerializer.Serialize(ref writer, message, serializerOptions);
|
||||
writer.Flush();
|
||||
return buffer.WrittenSpan.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
var v = BuildMessage();
|
||||
using (await asyncLock.LockAsync().ConfigureAwait(false))
|
||||
{
|
||||
await connection.RawStreamingCall.RequestStream.WriteAsync(v).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await tcs.Task; // wait until server return response(or error). if connection was closed, throws cancellation from DisposeAsyncCore.
|
||||
}
|
||||
|
||||
void ThrowIfDisposed()
|
||||
{
|
||||
if (disposed) throw new ObjectDisposedException("StreamingHubClient");
|
||||
}
|
||||
|
||||
public Task WaitForDisconnect()
|
||||
{
|
||||
return waitForDisconnect.Task;
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
return DisposeAsyncCore(true);
|
||||
}
|
||||
|
||||
async Task DisposeAsyncCore(bool waitSubscription)
|
||||
{
|
||||
if (disposed) return;
|
||||
if (connection.RawStreamingCall == null) return;
|
||||
|
||||
disposed = true;
|
||||
|
||||
try
|
||||
{
|
||||
await connection.RequestStream.CompleteAsync();
|
||||
}
|
||||
catch { } // ignore error?
|
||||
finally
|
||||
{
|
||||
cts.Cancel();
|
||||
cts.Dispose();
|
||||
try
|
||||
{
|
||||
if (waitSubscription)
|
||||
{
|
||||
if (subscription != null)
|
||||
{
|
||||
await subscription;
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup completion
|
||||
List<Exception> aggregateException = null;
|
||||
foreach (var item in responseFutures)
|
||||
{
|
||||
try
|
||||
{
|
||||
(item.Value as ITaskCompletion).TrySetCanceled();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!(ex is OperationCanceledException))
|
||||
{
|
||||
if (aggregateException != null)
|
||||
{
|
||||
aggregateException = new List<Exception>();
|
||||
aggregateException.Add(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aggregateException != null)
|
||||
{
|
||||
throw new AggregateException(aggregateException);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!(ex is OperationCanceledException))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d3ca190a4e3a9184ea0ba8b8c5e88b2f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,584 +0,0 @@
|
|||
#if NON_UNITY || !NET_STANDARD_2_0
|
||||
|
||||
using Grpc.Core;
|
||||
using Grpc.Core.Logging;
|
||||
using MagicOnion.Server.Hubs;
|
||||
using MagicOnion.Utils;
|
||||
using MessagePack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion.Client
|
||||
{
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class StreamingHubClientAssemblyHolder
|
||||
{
|
||||
public const string ModuleName = "MagicOnion.Client.StreamingHubClient";
|
||||
|
||||
readonly static DynamicAssembly assembly;
|
||||
internal static DynamicAssembly Assembly { get { return assembly; } }
|
||||
|
||||
static StreamingHubClientAssemblyHolder()
|
||||
{
|
||||
assembly = new DynamicAssembly(ModuleName);
|
||||
}
|
||||
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
|
||||
public static AssemblyBuilder Save()
|
||||
{
|
||||
return assembly.Save();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class StreamingHubClientBuilder<TStreamingHub, TReceiver>
|
||||
{
|
||||
public static readonly Type ClientType;
|
||||
// static readonly Type ClientFireAndForgetType;
|
||||
|
||||
static readonly Type bytesMethod = typeof(Method<,>).MakeGenericType(new[] { typeof(byte[]), typeof(byte[]) });
|
||||
static readonly FieldInfo throughMarshaller = typeof(MagicOnionMarshallers).GetField("ThroughMarshaller", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
static readonly ConstructorInfo notSupportedException = typeof(NotSupportedException).GetConstructor(Type.EmptyTypes);
|
||||
|
||||
static readonly MethodInfo callMessagePackDesrialize = typeof(MessagePackSerializer).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
|
||||
.First(x => x.Name == "Deserialize" && x.GetParameters().Length == 3 && x.GetParameters()[0].ParameterType == typeof(ReadOnlyMemory<byte>) && x.GetParameters()[1].ParameterType == typeof(MessagePackSerializerOptions));
|
||||
static readonly MethodInfo callCancellationTokenNone = typeof(CancellationToken).GetProperty("None", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetGetMethod();
|
||||
static readonly PropertyInfo completedTask = typeof(Task).GetProperty("CompletedTask", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
|
||||
|
||||
static StreamingHubClientBuilder()
|
||||
{
|
||||
var t = typeof(TStreamingHub);
|
||||
var ti = t.GetTypeInfo();
|
||||
if (!ti.IsInterface) throw new Exception("Client Proxy only allows interface. Type:" + ti.Name);
|
||||
var asm = StreamingHubClientAssemblyHolder.Assembly;
|
||||
var methodDefinitions = SearchDefinitions(t);
|
||||
|
||||
var parentType = typeof(StreamingHubClientBase<,>).MakeGenericType(typeof(TStreamingHub), typeof(TReceiver));
|
||||
var typeBuilder = asm.DefineType($"{DynamicClientAssemblyHolder.ModuleName}.{ti.FullName}StreamingHubClient_{Guid.NewGuid().ToString()}", TypeAttributes.Public, parentType, new Type[] { t });
|
||||
|
||||
VerifyMethodDefinitions(methodDefinitions);
|
||||
|
||||
{
|
||||
// Create FireAndForgetType first as nested type.
|
||||
var typeBuilderEx = typeBuilder.DefineNestedType($"FireAndForgetClient", TypeAttributes.NestedPrivate, typeof(object), new Type[] { t });
|
||||
var tuple = DefineFireAndForgetConstructor(typeBuilderEx, typeBuilder);
|
||||
var fireAndForgetClientCtor = tuple.Item1;
|
||||
var fireAndForgetField = tuple.Item2;
|
||||
|
||||
DefineMethodsFireAndForget(typeBuilderEx, t, fireAndForgetField, typeBuilder, methodDefinitions);
|
||||
typeBuilderEx.CreateTypeInfo(); // ok to create nested type.
|
||||
|
||||
var methodField = DefineStaticConstructor(typeBuilder, t);
|
||||
var clientField = DefineConstructor(typeBuilder, t, typeof(TReceiver), fireAndForgetClientCtor);
|
||||
DefineMethods(typeBuilder, t, typeof(TReceiver), methodField, clientField, methodDefinitions);
|
||||
}
|
||||
|
||||
ClientType = typeBuilder.CreateTypeInfo().AsType();
|
||||
}
|
||||
|
||||
static MethodDefinition[] SearchDefinitions(Type interfaceType)
|
||||
{
|
||||
return interfaceType
|
||||
.GetInterfaces()
|
||||
.Concat(new[] { interfaceType })
|
||||
.SelectMany(x => x.GetMethods())
|
||||
.Where(x =>
|
||||
{
|
||||
var methodInfo = x;
|
||||
if (methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_") || methodInfo.Name.StartsWith("get_"))) return false;
|
||||
if (methodInfo.GetCustomAttribute<IgnoreAttribute>(false) != null) return false; // ignore
|
||||
|
||||
var methodName = methodInfo.Name;
|
||||
if (methodName == "Equals"
|
||||
|| methodName == "GetHashCode"
|
||||
|| methodName == "GetType"
|
||||
|| methodName == "ToString"
|
||||
|| methodName == "DisposeAsync"
|
||||
|| methodName == "WaitForDisconnect"
|
||||
|| methodName == "FireAndForget"
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.Where(x => !x.IsSpecialName)
|
||||
.Select(x => new MethodDefinition
|
||||
{
|
||||
ServiceType = interfaceType,
|
||||
MethodInfo = x,
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
static void VerifyMethodDefinitions(MethodDefinition[] definitions)
|
||||
{
|
||||
var map = new Dictionary<int, MethodDefinition>(definitions.Length);
|
||||
foreach (var item in definitions)
|
||||
{
|
||||
var methodId = item.MethodInfo.GetCustomAttribute<MethodIdAttribute>()?.MethodId ?? FNV1A32.GetHashCode(item.MethodInfo.Name);
|
||||
if (map.ContainsKey(methodId))
|
||||
{
|
||||
throw new Exception($"TStreamingHub does not allows duplicate methodId(hash code). Please change name or use MethodIdAttribute. {map[methodId].MethodInfo.Name} and {item.MethodInfo.Name}");
|
||||
}
|
||||
map.Add(methodId, item);
|
||||
|
||||
if (!(item.MethodInfo.ReturnType.IsGenericType && item.MethodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
&& item.MethodInfo.ReturnType != typeof(Task))
|
||||
{
|
||||
throw new Exception($"Invalid definition, TStreamingHub's return type must only be `Task` or `Task<T>`. {item.MethodInfo.Name}.");
|
||||
}
|
||||
|
||||
item.MethodId = methodId;
|
||||
if (item.RequestType == null)
|
||||
{
|
||||
item.RequestType = MagicOnionMarshallers.CreateRequestType(item.MethodInfo.GetParameters());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static FieldInfo DefineStaticConstructor(TypeBuilder typeBuilder, Type interfaceType)
|
||||
{
|
||||
// static readonly Method<byte[], byte[]> method = new Method<byte[], byte[]>(MethodType.DuplexStreaming, "IFoo", "Connect", MagicOnionMarshallers.ThroughMarshaller, MagicOnionMarshallers.ThroughMarshaller);
|
||||
var field = typeBuilder.DefineField("method", bytesMethod, FieldAttributes.Private | FieldAttributes.Static);
|
||||
|
||||
var cctor = typeBuilder.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes);
|
||||
var il = cctor.GetILGenerator();
|
||||
|
||||
il.EmitLdc_I4((int)MethodType.DuplexStreaming);
|
||||
il.Emit(OpCodes.Ldstr, interfaceType.Name);
|
||||
il.Emit(OpCodes.Ldstr, "Connect");
|
||||
il.Emit(OpCodes.Ldsfld, throughMarshaller);
|
||||
il.Emit(OpCodes.Ldsfld, throughMarshaller);
|
||||
il.Emit(OpCodes.Newobj, bytesMethod.GetConstructors()[0]);
|
||||
il.Emit(OpCodes.Stsfld, field);
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
static FieldInfo DefineConstructor(TypeBuilder typeBuilder, Type interfaceType, Type receiverType, ConstructorInfo fireAndForgetClientCtor)
|
||||
{
|
||||
// .ctor(CallInvoker callInvoker, string host, CallOptions option, MessagePackSerializerOptions resolver, ILogger logger) :base(...)
|
||||
{
|
||||
var argTypes = new[] { typeof(CallInvoker), typeof(string), typeof(CallOptions), typeof(MessagePackSerializerOptions), typeof(ILogger) };
|
||||
var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, argTypes);
|
||||
var il = ctor.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
il.Emit(OpCodes.Ldarg_3);
|
||||
il.Emit(OpCodes.Ldarg_S, (byte)4);
|
||||
il.Emit(OpCodes.Ldarg_S, (byte)5);
|
||||
il.Emit(OpCodes.Call, typeBuilder.BaseType
|
||||
.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).First());
|
||||
|
||||
// { this.fireAndForgetClient = new FireAndForgetClient(this); }
|
||||
var clientField = typeBuilder.DefineField("fireAndForgetClient", fireAndForgetClientCtor.DeclaringType, FieldAttributes.Private);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Newobj, fireAndForgetClientCtor);
|
||||
il.Emit(OpCodes.Stfld, clientField);
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
return clientField;
|
||||
}
|
||||
}
|
||||
|
||||
static Tuple<ConstructorBuilder, FieldBuilder> DefineFireAndForgetConstructor(TypeBuilder typeBuilder, Type parentClientType)
|
||||
{
|
||||
// .ctor(Parent client) { this.client = client }
|
||||
{
|
||||
var argTypes = new[] { parentClientType };
|
||||
var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, argTypes);
|
||||
var clientField = typeBuilder.DefineField("client", parentClientType, FieldAttributes.Private);
|
||||
var il = ctor.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, typeof(object).GetConstructors().First());
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Stfld, clientField);
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
return Tuple.Create(ctor, clientField);
|
||||
}
|
||||
}
|
||||
|
||||
static void DefineMethods(TypeBuilder typeBuilder, Type interfaceType, Type receiverType, FieldInfo methodField, FieldInfo clientField, MethodDefinition[] definitions)
|
||||
{
|
||||
var baseType = typeof(StreamingHubClientBase<,>).MakeGenericType(interfaceType, receiverType);
|
||||
var serializerOptionsField = baseType.GetField("serializerOptions", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var receiverField = baseType.GetField("receiver", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
// protected abstract Method<byte[], byte[]> DuplexStreamingAsyncMethod { get; }
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("get_DuplexStreamingAsyncMethod", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
bytesMethod,
|
||||
Type.EmptyTypes);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, methodField);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
{
|
||||
// Task DisposeAsync();
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("DisposeAsync", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
typeof(Task), Type.EmptyTypes);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, baseType.GetMethod("DisposeAsync", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
// Task WaitForDisconnect();
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("WaitForDisconnect", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
typeof(Task), Type.EmptyTypes);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Call, baseType.GetMethod("WaitForDisconnect", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
// TSelf FireAndForget();
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("FireAndForget", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
interfaceType, Type.EmptyTypes);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, clientField);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
|
||||
// receiver types borrow from DynamicBroadcastBuilder
|
||||
{
|
||||
// protected abstract void OnResponseEvent(int methodId, object taskCompletionSource, ArraySegment<byte> data);
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("OnResponseEvent", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
null, new[] { typeof(int), typeof(object), typeof(ArraySegment<byte>) });
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
var labels = definitions
|
||||
.Select(x => new { def = x, label = il.DefineLabel() })
|
||||
.ToArray();
|
||||
|
||||
foreach (var item in labels)
|
||||
{
|
||||
// if( == ) goto ...
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.EmitLdc_I4(item.def.MethodId);
|
||||
il.Emit(OpCodes.Beq, item.label);
|
||||
}
|
||||
// else
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
foreach (var item in labels)
|
||||
{
|
||||
// var result = LZ4MessagePackSerializer.Deserialize<T>(data, resolver);
|
||||
// ((TaskCompletionSource<T>)taskCompletionSource).TrySetResult(result);
|
||||
|
||||
// => ((TaskCompletionSource<T>)taskCompletionSource).TrySetResult(LZ4MessagePackSerializer.Deserialize<T>(data, resolver));
|
||||
|
||||
Type responseType;
|
||||
Type tcsType;
|
||||
if (item.def.MethodInfo.ReturnType == typeof(Task))
|
||||
{
|
||||
// Task methods uses TaskCompletionSource<Nil>
|
||||
responseType = typeof(Nil);
|
||||
tcsType = typeof(TaskCompletionSource<Nil>);
|
||||
}
|
||||
else
|
||||
{
|
||||
responseType = item.def.MethodInfo.ReturnType.GetGenericArguments()[0];
|
||||
tcsType = typeof(TaskCompletionSource<>).MakeGenericType(responseType);
|
||||
}
|
||||
|
||||
il.MarkLabel(item.label);
|
||||
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
il.Emit(OpCodes.Castclass, tcsType);
|
||||
il.Emit(OpCodes.Ldarg_3);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Call, callCancellationTokenNone);
|
||||
il.Emit(OpCodes.Call, callMessagePackDesrialize.MakeGenericMethod(responseType));
|
||||
|
||||
il.Emit(OpCodes.Callvirt, tcsType.GetMethod("TrySetResult"));
|
||||
il.Emit(OpCodes.Pop);
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
// protected abstract void OnBroadcastEvent(int methodId, ArraySegment<byte> data);
|
||||
{
|
||||
var methodDefinitions = BroadcasterHelper.SearchDefinitions(receiverType);
|
||||
BroadcasterHelper.VerifyMethodDefinitions(methodDefinitions);
|
||||
|
||||
var method = typeBuilder.DefineMethod("OnBroadcastEvent", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
typeof(void), new[] { typeof(int), typeof(ArraySegment<byte>) });
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
var labels = methodDefinitions
|
||||
.Select(x => new { def = x, label = il.DefineLabel() })
|
||||
.ToArray();
|
||||
|
||||
foreach (var item in labels)
|
||||
{
|
||||
// if( == ) goto ...
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.EmitLdc_I4(item.def.MethodId);
|
||||
il.Emit(OpCodes.Beq, item.label);
|
||||
}
|
||||
// else
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
foreach (var item in labels)
|
||||
{
|
||||
il.MarkLabel(item.label);
|
||||
|
||||
// var result = LZ4MessagePackSerializer.Deserialize<DynamicArgumentTuple<int, string>>(data, resolver);
|
||||
// return receiver.OnReceiveMessage(result.Item1, result.Item2);
|
||||
|
||||
var parameters = item.def.MethodInfo.GetParameters();
|
||||
if (parameters.Length == 0)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, receiverField);
|
||||
il.Emit(OpCodes.Callvirt, item.def.MethodInfo);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
else if (parameters.Length == 1)
|
||||
{
|
||||
// TODO:fix emit
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, receiverField);
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Call, callCancellationTokenNone);
|
||||
il.Emit(OpCodes.Call, callMessagePackDesrialize.MakeGenericMethod(parameters[0].ParameterType));
|
||||
il.Emit(OpCodes.Callvirt, item.def.MethodInfo);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO:fix emit
|
||||
var deserializeType = BroadcasterHelper.dynamicArgumentTupleTypes[parameters.Length - 2]
|
||||
.MakeGenericType(parameters.Select(x => x.ParameterType).ToArray());
|
||||
var lc = il.DeclareLocal(deserializeType);
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, serializerOptionsField);
|
||||
il.Emit(OpCodes.Call, callCancellationTokenNone);
|
||||
il.Emit(OpCodes.Call, callMessagePackDesrialize.MakeGenericMethod(deserializeType));
|
||||
il.Emit(OpCodes.Stloc, lc);
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, receiverField);
|
||||
for (int i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
il.Emit(OpCodes.Ldloc, lc);
|
||||
il.Emit(OpCodes.Ldfld, deserializeType.GetField("Item" + (i + 1)));
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Callvirt, item.def.MethodInfo);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Proxy Methods
|
||||
for (int i = 0; i < definitions.Length; i++)
|
||||
{
|
||||
var def = definitions[i];
|
||||
var parameters = def.MethodInfo.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||
|
||||
var method = typeBuilder.DefineMethod(def.MethodInfo.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
def.MethodInfo.ReturnType,
|
||||
parameters);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
// return WriteMessageAsync<T>(methodId, message);
|
||||
// return WriteMessageWithResponseAsync<TReq, TRes>(methodId, message);
|
||||
|
||||
// this.***
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
|
||||
// arg1
|
||||
il.EmitLdc_I4(def.MethodId);
|
||||
|
||||
// create request for arg2
|
||||
for (int j = 0; j < parameters.Length; j++)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg, j + 1);
|
||||
}
|
||||
|
||||
Type callType = null;
|
||||
if (parameters.Length == 0)
|
||||
{
|
||||
// use Nil.
|
||||
callType = typeof(Nil);
|
||||
il.Emit(OpCodes.Ldsfld, typeof(Nil).GetField("Default"));
|
||||
}
|
||||
else if (parameters.Length == 1)
|
||||
{
|
||||
// already loaded parameter.
|
||||
callType = parameters[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// call new DynamicArgumentTuple<T>
|
||||
callType = def.RequestType;
|
||||
il.Emit(OpCodes.Newobj, callType.GetConstructors().First());
|
||||
}
|
||||
|
||||
if (def.MethodInfo.ReturnType == typeof(Task))
|
||||
{
|
||||
var mInfo = baseType.GetMethod("WriteMessageWithResponseAsync", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
il.Emit(OpCodes.Callvirt, mInfo.MakeGenericMethod(callType, typeof(Nil)));
|
||||
}
|
||||
else
|
||||
{
|
||||
var mInfo = baseType.GetMethod("WriteMessageWithResponseAsync", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
il.Emit(OpCodes.Callvirt, mInfo.MakeGenericMethod(callType, def.MethodInfo.ReturnType.GetGenericArguments()[0]));
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void DefineMethodsFireAndForget(TypeBuilder typeBuilder, Type interfaceType, FieldInfo clientField, Type parentNestedType, MethodDefinition[] definitions)
|
||||
{
|
||||
{
|
||||
// Task DisposeAsync();
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("DisposeAsync", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
typeof(Task), Type.EmptyTypes);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Newobj, notSupportedException);
|
||||
il.Emit(OpCodes.Throw);
|
||||
}
|
||||
// Task WaitForDisconnect();
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("WaitForDisconnect", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
typeof(Task), Type.EmptyTypes);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Newobj, notSupportedException);
|
||||
il.Emit(OpCodes.Throw);
|
||||
}
|
||||
// TSelf FireAndForget();
|
||||
{
|
||||
var method = typeBuilder.DefineMethod("FireAndForget", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
interfaceType, Type.EmptyTypes);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Newobj, notSupportedException);
|
||||
il.Emit(OpCodes.Throw);
|
||||
}
|
||||
}
|
||||
|
||||
// Proxy Methods
|
||||
for (int i = 0; i < definitions.Length; i++)
|
||||
{
|
||||
var def = definitions[i];
|
||||
var parameters = def.MethodInfo.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||
|
||||
var method = typeBuilder.DefineMethod(def.MethodInfo.Name, MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
|
||||
def.MethodInfo.ReturnType,
|
||||
parameters);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
// return client.WriteMessage***<T>(methodId, message);
|
||||
|
||||
// this.client.***
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldfld, clientField);
|
||||
|
||||
// arg1
|
||||
il.EmitLdc_I4(def.MethodId);
|
||||
|
||||
// create request for arg2
|
||||
for (int j = 0; j < parameters.Length; j++)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg, j + 1);
|
||||
}
|
||||
|
||||
Type callType = null;
|
||||
if (parameters.Length == 0)
|
||||
{
|
||||
// use Nil.
|
||||
callType = typeof(Nil);
|
||||
il.Emit(OpCodes.Ldsfld, typeof(Nil).GetField("Default"));
|
||||
}
|
||||
else if (parameters.Length == 1)
|
||||
{
|
||||
// already loaded parameter.
|
||||
callType = parameters[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// call new DynamicArgumentTuple<T>
|
||||
callType = def.RequestType;
|
||||
il.Emit(OpCodes.Newobj, callType.GetConstructors().First());
|
||||
}
|
||||
|
||||
if (def.MethodInfo.ReturnType == typeof(Task))
|
||||
{
|
||||
var mInfo = parentNestedType.BaseType.GetMethod("WriteMessageAsync", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
il.Emit(OpCodes.Callvirt, mInfo.MakeGenericMethod(callType));
|
||||
}
|
||||
else
|
||||
{
|
||||
var mInfo = parentNestedType.BaseType.GetMethod("WriteMessageAsyncFireAndForget", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
il.Emit(OpCodes.Callvirt, mInfo.MakeGenericMethod(callType, def.MethodInfo.ReturnType.GetGenericArguments()[0]));
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MethodDefinition
|
||||
{
|
||||
public string Path => ServiceType.Name + "/" + MethodInfo.Name;
|
||||
|
||||
public Type ServiceType;
|
||||
public MethodInfo MethodInfo;
|
||||
public int MethodId;
|
||||
|
||||
public Type RequestType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 88e3748798a988c4482dafe8624b1400
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cf5ef5626f3854c41ae7c68935ada7c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "MagicOnion",
|
||||
"references": [
|
||||
"MessagePack",
|
||||
"MagicOnion.Abstractions"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 204215817eaff0c4eaa0f2b9cdd2df52
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using MessagePack;
|
||||
using MessagePack.Formatters;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
internal class MarshallingAsyncStreamReader<T> : IAsyncStreamReader<T>, IDisposable
|
||||
{
|
||||
readonly IAsyncStreamReader<byte[]> inner;
|
||||
readonly MessagePackSerializerOptions options;
|
||||
|
||||
public MarshallingAsyncStreamReader(IAsyncStreamReader<byte[]> inner, MessagePackSerializerOptions options)
|
||||
{
|
||||
this.inner = inner;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public T Current { get; private set; }
|
||||
|
||||
public async Task<bool> MoveNext(CancellationToken cancellationToken)
|
||||
{
|
||||
if (await inner.MoveNext(cancellationToken))
|
||||
{
|
||||
this.Current = MessagePackSerializer.Deserialize<T>(inner.Current, options);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
(inner as IDisposable)?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal class MarshallingClientStreamWriter<T> : IClientStreamWriter<T>
|
||||
{
|
||||
readonly IClientStreamWriter<byte[]> inner;
|
||||
readonly MessagePackSerializerOptions options;
|
||||
|
||||
public MarshallingClientStreamWriter(IClientStreamWriter<byte[]> inner, MessagePackSerializerOptions options)
|
||||
{
|
||||
this.inner = inner;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public WriteOptions WriteOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
return inner.WriteOptions;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
inner.WriteOptions = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Task CompleteAsync()
|
||||
{
|
||||
return inner.CompleteAsync();
|
||||
}
|
||||
|
||||
public Task WriteAsync(T message)
|
||||
{
|
||||
var bytes = MessagePackSerializer.Serialize(message, options);
|
||||
return inner.WriteAsync(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// invoke from dynamic methods so must be public
|
||||
public static class MagicOnionMarshallers
|
||||
{
|
||||
static readonly Type[] dynamicArgumentTupleTypes = typeof(DynamicArgumentTuple<,>).GetTypeInfo().Assembly
|
||||
.GetTypes()
|
||||
.Where(x => x.Name.StartsWith("DynamicArgumentTuple") && !x.Name.Contains("Formatter"))
|
||||
.OrderBy(x => x.GetGenericArguments().Length)
|
||||
.ToArray();
|
||||
|
||||
static readonly Type[] dynamicArgumentTupleFormatterTypes = typeof(DynamicArgumentTupleFormatter<,,>).GetTypeInfo().Assembly
|
||||
.GetTypes()
|
||||
.Where(x => x.Name.StartsWith("DynamicArgumentTupleFormatter"))
|
||||
.OrderBy(x => x.GetGenericArguments().Length)
|
||||
.ToArray();
|
||||
|
||||
public static readonly byte[] UnsafeNilBytes = new byte[] { MessagePackCode.Nil };
|
||||
|
||||
public static readonly Marshaller<byte[]> ThroughMarshaller = new Marshaller<byte[]>(x => x, x => x);
|
||||
|
||||
internal static Type CreateRequestType(ParameterInfo[] parameters)
|
||||
{
|
||||
if (parameters.Length == 0)
|
||||
{
|
||||
return typeof(byte[]);
|
||||
}
|
||||
else if (parameters.Length == 1)
|
||||
{
|
||||
var t = parameters[0].ParameterType;
|
||||
return t;
|
||||
}
|
||||
else if (parameters.Length > 20)
|
||||
{
|
||||
throw new InvalidOperationException($"Parameter length must be <= 20, length:{parameters.Length}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// start from T2
|
||||
var tupleTypeBase = dynamicArgumentTupleTypes[parameters.Length - 2];
|
||||
var t = tupleTypeBase.MakeGenericType(parameters.Select(x => x.ParameterType).ToArray());
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
public static Type CreateRequestTypeAndSetResolver(string path, ParameterInfo[] parameters, ref IFormatterResolver resolver)
|
||||
{
|
||||
if (parameters.Length == 0)
|
||||
{
|
||||
return typeof(byte[]);
|
||||
}
|
||||
else if (parameters.Length == 1)
|
||||
{
|
||||
return parameters[0].ParameterType;
|
||||
}
|
||||
else if (parameters.Length > 20)
|
||||
{
|
||||
throw new InvalidOperationException($"Parameter length must be <= 20, path:{path} length:{parameters.Length}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// start from T2
|
||||
var tupleTypeBase = dynamicArgumentTupleTypes[parameters.Length - 2];
|
||||
var formatterTypeBase = dynamicArgumentTupleFormatterTypes[parameters.Length - 2];
|
||||
|
||||
var t = tupleTypeBase.MakeGenericType(parameters.Select(x => x.ParameterType).ToArray());
|
||||
var formatterType = formatterTypeBase.MakeGenericType(parameters.Select(x => x.ParameterType).ToArray());
|
||||
|
||||
var defaultValues = parameters
|
||||
.Select(x =>
|
||||
{
|
||||
if (x.HasDefaultValue)
|
||||
{
|
||||
return x.DefaultValue;
|
||||
}
|
||||
else if (x.ParameterType.GetTypeInfo().IsValueType)
|
||||
{
|
||||
return Activator.CreateInstance(x.ParameterType);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}).ToArray();
|
||||
|
||||
var formatter = Activator.CreateInstance(formatterType, defaultValues);
|
||||
|
||||
resolver = new PriorityResolver(t, formatter, resolver);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
public static object InstantiateDynamicArgumentTuple(Type[] typeParameters, object[] arguments)
|
||||
{
|
||||
// start from T2
|
||||
var tupleTypeBase = dynamicArgumentTupleTypes[arguments.Length - 2];
|
||||
return Activator.CreateInstance(tupleTypeBase.MakeGenericType(typeParameters), arguments);
|
||||
}
|
||||
}
|
||||
|
||||
internal class PriorityResolver : IFormatterResolver
|
||||
{
|
||||
readonly Type formatterType;
|
||||
readonly object formatter;
|
||||
readonly IFormatterResolver innerResolver;
|
||||
|
||||
public PriorityResolver(Type formatterType, object formatter, IFormatterResolver innerResolver)
|
||||
{
|
||||
this.formatterType = formatterType;
|
||||
this.formatter = formatter;
|
||||
this.innerResolver = innerResolver;
|
||||
}
|
||||
|
||||
public IMessagePackFormatter<T> GetFormatter<T>()
|
||||
{
|
||||
if (typeof(T) == formatterType)
|
||||
{
|
||||
return (IMessagePackFormatter<T>)formatter;
|
||||
}
|
||||
else if (innerResolver == null)
|
||||
{
|
||||
return MessagePackSerializer.DefaultOptions.Resolver.GetFormatterWithVerify<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return innerResolver.GetFormatterWithVerify<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 667fe11f4c8014340bbde4521d337330
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using System;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
public static class MetadataExtensions
|
||||
{
|
||||
public const string BinarySuffix = "-bin";
|
||||
|
||||
/// <summary>
|
||||
/// Get metdata entry. If does not exists, return null.
|
||||
/// </summary>
|
||||
public static Metadata.Entry Get(this Metadata metadata, string key, bool ignoreCase = true)
|
||||
{
|
||||
for (int i = 0; i < metadata.Count; i++)
|
||||
{
|
||||
var entry = metadata[i];
|
||||
if (ignoreCase)
|
||||
{
|
||||
if (entry.Key.Equals(key, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entry.Key == key)
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get metdata string value. If does not exists, return null.
|
||||
/// </summary>
|
||||
public static string GetValue(this Metadata metadata, string key, bool ignoreCase = true)
|
||||
{
|
||||
for (int i = 0; i < metadata.Count; i++)
|
||||
{
|
||||
var entry = metadata[i];
|
||||
if (ignoreCase)
|
||||
{
|
||||
if (entry.Key.Equals(key, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return entry.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entry.Key == key)
|
||||
{
|
||||
return entry.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ad9313e64fc51ed44a50cb156e479929
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
using Grpc.Core;
|
||||
using System;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
public class ReturnStatusException : Exception
|
||||
{
|
||||
public StatusCode StatusCode { get; private set; }
|
||||
public string Detail { get; private set; }
|
||||
|
||||
public ReturnStatusException(StatusCode statusCode, string detail)
|
||||
{
|
||||
this.StatusCode = statusCode;
|
||||
this.Detail = detail;
|
||||
}
|
||||
|
||||
public Status ToStatus()
|
||||
{
|
||||
return new Status(StatusCode, Detail ?? "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b4c3bb3dea67c86419674cd758cfa7ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e463862d96bbe2e4c8060ea4f8256eff
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5c9aa9fba89d3404eb2292310360d574
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
using MagicOnion.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MagicOnion.Server.Hubs
|
||||
{
|
||||
public static class BroadcasterHelper
|
||||
{
|
||||
internal static readonly Type[] dynamicArgumentTupleTypes = typeof(DynamicArgumentTuple<,>).GetTypeInfo().Assembly
|
||||
.GetTypes()
|
||||
.Where(x => x.Name.StartsWith("DynamicArgumentTuple") && !x.Name.Contains("Formatter"))
|
||||
.OrderBy(x => x.GetGenericArguments().Length)
|
||||
.ToArray();
|
||||
|
||||
internal static MethodDefinition[] SearchDefinitions(Type interfaceType)
|
||||
{
|
||||
return interfaceType
|
||||
.GetInterfaces()
|
||||
.Concat(new[] { interfaceType })
|
||||
.SelectMany(x => x.GetMethods())
|
||||
.Where(x =>
|
||||
{
|
||||
var methodInfo = x;
|
||||
if (methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_") || methodInfo.Name.StartsWith("get_"))) return false;
|
||||
if (methodInfo.GetCustomAttribute<IgnoreAttribute>(false) != null) return false; // ignore
|
||||
|
||||
var methodName = methodInfo.Name;
|
||||
if (methodName == "Equals"
|
||||
|| methodName == "GetHashCode"
|
||||
|| methodName == "GetType"
|
||||
|| methodName == "ToString"
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.Where(x => !x.IsSpecialName)
|
||||
.Select(x => new MethodDefinition
|
||||
{
|
||||
ReceiverType = interfaceType,
|
||||
MethodInfo = x,
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
internal static void VerifyMethodDefinitions(MethodDefinition[] definitions)
|
||||
{
|
||||
// define and set.
|
||||
var map = new Dictionary<int, MethodDefinition>(definitions.Length);
|
||||
foreach (var item in definitions)
|
||||
{
|
||||
var methodId = item.MethodInfo.GetCustomAttribute<MethodIdAttribute>()?.MethodId ?? FNV1A32.GetHashCode(item.MethodInfo.Name);
|
||||
if (map.ContainsKey(methodId))
|
||||
{
|
||||
throw new Exception($"TReceiver does not allows duplicate methodId(hash code). Please change name or use MethodIdAttribute. {map[methodId].MethodInfo.Name} and {item.MethodInfo.Name}");
|
||||
}
|
||||
map.Add(methodId, item);
|
||||
|
||||
if (!(item.MethodInfo.ReturnType == typeof(void)))
|
||||
{
|
||||
throw new Exception($"Invalid definition, TReceiver's return type must only be `void`. {item.MethodInfo.Name}.");
|
||||
}
|
||||
|
||||
item.MethodId = methodId;
|
||||
}
|
||||
}
|
||||
|
||||
public static async void FireAndForget(Task task)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task.ConfigureAwait(false);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Grpc.Core.GrpcEnvironment.Logger?.Error(ex, "exception occured in client broadcast.");
|
||||
}
|
||||
}
|
||||
|
||||
internal class MethodDefinition
|
||||
{
|
||||
public string Path => ReceiverType.Name + "/" + MethodInfo.Name;
|
||||
|
||||
public Type ReceiverType;
|
||||
public MethodInfo MethodInfo;
|
||||
public int MethodId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a482aff8c25287942af22c031e219f8d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
using MessagePack;
|
||||
using System.Buffers;
|
||||
using MessagePack.Formatters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MagicOnion
|
||||
{
|
||||
public class UnsafeDirectBlitResolver : IFormatterResolver
|
||||
{
|
||||
public static readonly UnsafeDirectBlitResolver Instance = new UnsafeDirectBlitResolver();
|
||||
|
||||
bool isFreezed = false;
|
||||
Dictionary<Type, object> formatters = new Dictionary<Type, object>();
|
||||
|
||||
UnsafeDirectBlitResolver()
|
||||
{
|
||||
}
|
||||
|
||||
public void Register<T>()
|
||||
where T : unmanaged
|
||||
{
|
||||
if (isFreezed)
|
||||
{
|
||||
throw new InvalidOperationException("Register must call on startup(before use GetFormatter<T>).");
|
||||
}
|
||||
|
||||
formatters.Add(typeof(T), new UnsafeDirectBlitFormatter<T>());
|
||||
formatters.Add(typeof(T[]), new UnsafeDirectBlitArrayFormatter<T>());
|
||||
}
|
||||
|
||||
public IMessagePackFormatter<T> GetFormatter<T>()
|
||||
{
|
||||
return FormatterCache<T>.formatter;
|
||||
}
|
||||
|
||||
static class FormatterCache<T>
|
||||
{
|
||||
public static readonly IMessagePackFormatter<T> formatter;
|
||||
|
||||
static FormatterCache()
|
||||
{
|
||||
Instance.isFreezed = true;
|
||||
|
||||
var t = typeof(T);
|
||||
|
||||
object formatterObject;
|
||||
if (Instance.formatters.TryGetValue(t, out formatterObject))
|
||||
{
|
||||
formatter = (IMessagePackFormatter<T>)formatterObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UnsafeDirectBlitArrayFormatter<T> : IMessagePackFormatter<T[]>
|
||||
where T : unmanaged
|
||||
{
|
||||
const int TypeCode = 45;
|
||||
|
||||
// use ext instead of ArrayFormatter for extremely boostup performance.
|
||||
// Layout: [extHeader, isLittlEendian(bool), bytes()]
|
||||
|
||||
readonly int StructLength;
|
||||
|
||||
public UnsafeDirectBlitArrayFormatter()
|
||||
{
|
||||
this.StructLength = Unsafe.SizeOf<T>();
|
||||
}
|
||||
|
||||
public void Serialize(ref MessagePackWriter writer, T[] value, MessagePackSerializerOptions options)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNil();
|
||||
return;
|
||||
}
|
||||
|
||||
var byteLen = value.Length * StructLength;
|
||||
writer.WriteExtensionFormatHeader(new ExtensionHeader(TypeCode, byteLen + 1));
|
||||
writer.Write(BitConverter.IsLittleEndian);
|
||||
|
||||
/*
|
||||
Span<byte> span = writer.GetSpan();
|
||||
Unsafe.CopyBlockUnaligned(ref span[0], ref Unsafe.As<T, byte>(ref value[0]), (uint)byteLen);
|
||||
writer.Advance(byteLen);
|
||||
*/
|
||||
|
||||
// currently can not write directly, wait msgpack update.
|
||||
var span = System.Buffers.ArrayPool<byte>.Shared.Rent(byteLen);
|
||||
try
|
||||
{
|
||||
Unsafe.CopyBlockUnaligned(ref span[0], ref Unsafe.As<T, byte>(ref value[0]), (uint)byteLen);
|
||||
writer.WriteRaw(span.AsSpan().Slice(0, byteLen));
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.Buffers.ArrayPool<byte>.Shared.Return(span);
|
||||
}
|
||||
}
|
||||
|
||||
public T[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
|
||||
{
|
||||
if (reader.IsNil)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var ext = reader.ReadExtensionFormat();
|
||||
if (ext.Header.TypeCode != TypeCode) throw new InvalidOperationException("Invalid typeCode.");
|
||||
|
||||
var extReader = new MessagePackReader(ext.Data);
|
||||
var isLittleEndian = extReader.ReadBoolean();
|
||||
|
||||
// extReader.read
|
||||
byte[] rentMemory = default;
|
||||
ReadOnlySpan<byte> span = default;
|
||||
{
|
||||
var seqSlice = extReader.Sequence.Slice(extReader.Position);
|
||||
if (isLittleEndian != BitConverter.IsLittleEndian)
|
||||
{
|
||||
rentMemory = ArrayPool<byte>.Shared.Rent((int)seqSlice.Length);
|
||||
seqSlice.CopyTo(rentMemory);
|
||||
Array.Reverse(rentMemory);
|
||||
span = rentMemory;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seqSlice.IsSingleSegment)
|
||||
{
|
||||
span = seqSlice.First.Span;
|
||||
}
|
||||
else
|
||||
{
|
||||
rentMemory = ArrayPool<byte>.Shared.Rent((int)seqSlice.Length);
|
||||
seqSlice.CopyTo(rentMemory);
|
||||
span = rentMemory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result = new T[span.Length / StructLength];
|
||||
Unsafe.CopyBlockUnaligned(ref Unsafe.As<T, byte>(ref result[0]), ref MemoryMarshal.GetReference(span), (uint)span.Length);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class UnsafeDirectBlitFormatter<T> : IMessagePackFormatter<T>
|
||||
where T : unmanaged
|
||||
{
|
||||
readonly int size;
|
||||
|
||||
public UnsafeDirectBlitFormatter()
|
||||
{
|
||||
// Note: check is T blittable?
|
||||
this.size = Unsafe.SizeOf<T>();
|
||||
}
|
||||
|
||||
public void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options)
|
||||
{
|
||||
// fix to v2.0-stable
|
||||
byte[] rentMemory = ArrayPool<byte>.Shared.Rent(size);
|
||||
try
|
||||
{
|
||||
var span = rentMemory.AsSpan().Slice(size);
|
||||
Unsafe.WriteUnaligned(ref span[0], value);
|
||||
writer.Write(span);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(rentMemory);
|
||||
}
|
||||
}
|
||||
|
||||
public T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
|
||||
{
|
||||
var segment = reader.ReadBytes();
|
||||
if (segment == null)
|
||||
{
|
||||
throw new InvalidOperationException("data is null");
|
||||
}
|
||||
|
||||
ValidateRead(segment.Value.Length);
|
||||
|
||||
if (segment.Value.IsSingleSegment)
|
||||
{
|
||||
var firstMemory = segment.Value.First;
|
||||
return Unsafe.ReadUnaligned<T>(ref MemoryMarshal.GetReference(firstMemory.Span));
|
||||
}
|
||||
else
|
||||
{
|
||||
var memory = segment.Value.ToArray();
|
||||
return Unsafe.ReadUnaligned<T>(ref memory[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateRead(long length)
|
||||
{
|
||||
if (length < size)
|
||||
{
|
||||
throw new InvalidOperationException("Overflow");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 02eef94aae0af164983a0d182274bc8d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
|
||||
namespace MagicOnion.Utils
|
||||
{
|
||||
internal sealed class ArrayPoolBufferWriter : IBufferWriter<byte>, IDisposable
|
||||
{
|
||||
[ThreadStatic]
|
||||
static ArrayPoolBufferWriter staticInstance;
|
||||
|
||||
public static ArrayPoolBufferWriter RentThreadStaticWriter()
|
||||
{
|
||||
if (staticInstance == null)
|
||||
{
|
||||
staticInstance = new ArrayPoolBufferWriter();
|
||||
}
|
||||
staticInstance.Prepare();
|
||||
return staticInstance;
|
||||
}
|
||||
|
||||
const int MinimumBufferSize = 32767; // use 32k buffer.
|
||||
|
||||
byte[] buffer;
|
||||
int index;
|
||||
|
||||
void Prepare()
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
buffer = ArrayPool<byte>.Shared.Rent(MinimumBufferSize);
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
|
||||
public ReadOnlyMemory<byte> WrittenMemory => buffer.AsMemory(0, index);
|
||||
public ReadOnlySpan<byte> WrittenSpan => buffer.AsSpan(0, index);
|
||||
|
||||
public int WrittenCount => index;
|
||||
|
||||
public int Capacity => buffer.Length;
|
||||
|
||||
public int FreeCapacity => buffer.Length - index;
|
||||
|
||||
public void Advance(int count)
|
||||
{
|
||||
if (count < 0) throw new ArgumentException(nameof(count));
|
||||
index += count;
|
||||
}
|
||||
|
||||
public Memory<byte> GetMemory(int sizeHint = 0)
|
||||
{
|
||||
CheckAndResizeBuffer(sizeHint);
|
||||
return buffer.AsMemory(index);
|
||||
}
|
||||
|
||||
public Span<byte> GetSpan(int sizeHint = 0)
|
||||
{
|
||||
CheckAndResizeBuffer(sizeHint);
|
||||
return buffer.AsSpan(index);
|
||||
}
|
||||
|
||||
void CheckAndResizeBuffer(int sizeHint)
|
||||
{
|
||||
if (sizeHint < 0) throw new ArgumentException(nameof(sizeHint));
|
||||
|
||||
if (sizeHint == 0)
|
||||
{
|
||||
sizeHint = MinimumBufferSize;
|
||||
}
|
||||
|
||||
int availableSpace = buffer.Length - index;
|
||||
|
||||
if (sizeHint > availableSpace)
|
||||
{
|
||||
int growBy = Math.Max(sizeHint, buffer.Length);
|
||||
|
||||
int newSize = checked(buffer.Length + growBy);
|
||||
|
||||
byte[] oldBuffer = buffer;
|
||||
|
||||
buffer = ArrayPool<byte>.Shared.Rent(newSize);
|
||||
|
||||
Span<byte> previousBuffer = oldBuffer.AsSpan(0, index);
|
||||
previousBuffer.CopyTo(buffer);
|
||||
ArrayPool<byte>.Shared.Return(oldBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
buffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3c3adb89f0d51ea448be279645a9c04c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
#if net45
|
||||
using System.Collections;
|
||||
using System.Runtime.Remoting;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
/// <summary>
|
||||
/// Polyfill for AsyncLocal functionality added in NETSTANDARD1.3 and .NET 4.6
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// The type of the value to encapsulate and follow.
|
||||
/// </typeparam>
|
||||
internal class AsyncLocal<T>
|
||||
{
|
||||
private readonly string _name = Guid.NewGuid().ToString("N");
|
||||
|
||||
/// <summary>
|
||||
/// Gets or set the value to flow with <see cref="ExecutionContext"/>.
|
||||
/// </summary>
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CallContext.LogicalGetData(_name) is ObjectHandle slot)
|
||||
return (T)slot.Unwrap();
|
||||
return default(T);
|
||||
}
|
||||
set
|
||||
{
|
||||
// Mimic the implementation of AsyncLocal<T>
|
||||
var executionContext = Thread.CurrentThread.GetMutableExecutionContext();
|
||||
var logicalCallContext = executionContext.GetLogicalCallContext();
|
||||
var datastore = logicalCallContext.GetDatastore();
|
||||
var datastoreCopy = datastore == null ? new Hashtable() : new Hashtable(datastore);
|
||||
var slot = new ObjectHandle(value);
|
||||
datastoreCopy[_name] = slot;
|
||||
logicalCallContext.SetDatastore(datastoreCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ThreadExtensions
|
||||
{
|
||||
private static readonly Func<Thread, ExecutionContext> _getMutableExecutionContextFunc;
|
||||
|
||||
static ThreadExtensions()
|
||||
{
|
||||
var getMutableExecutionContextMethodInfo = typeof(Thread).GetMethod("GetMutableExecutionContext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var instanceParameterExpression = Expression.Parameter(typeof(Thread));
|
||||
var functionCallExpression = Expression.Call(instanceParameterExpression, getMutableExecutionContextMethodInfo);
|
||||
var lambdaExpression = Expression.Lambda<Func<Thread, ExecutionContext>>(functionCallExpression, instanceParameterExpression);
|
||||
_getMutableExecutionContextFunc = lambdaExpression.Compile();
|
||||
}
|
||||
|
||||
private static MethodInfo GetMutableExecutionContextMethodInfo =
|
||||
typeof(Thread).GetMethod("GetMutableExecutionContext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
public static ExecutionContext GetMutableExecutionContext(this Thread thread)
|
||||
=> _getMutableExecutionContextFunc(thread);
|
||||
}
|
||||
|
||||
internal static class LogicalCallContextExtensions
|
||||
{
|
||||
private static readonly Func<LogicalCallContext, Hashtable> _getDatastoreFunc;
|
||||
private static readonly Func<LogicalCallContext, Hashtable, bool> _setDatastoreFunc;
|
||||
|
||||
static LogicalCallContextExtensions()
|
||||
{
|
||||
var datastoreFieldInfo = typeof(LogicalCallContext).GetField("m_Datastore", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
var instanceParameterExpression = Expression.Parameter(typeof(LogicalCallContext));
|
||||
var memberAccessExpression = Expression.MakeMemberAccess(instanceParameterExpression, datastoreFieldInfo);
|
||||
var getLambdaExpression = Expression.Lambda<Func<LogicalCallContext, Hashtable>>(memberAccessExpression, instanceParameterExpression);
|
||||
_getDatastoreFunc = getLambdaExpression.Compile();
|
||||
var valueParameterExpression = Expression.Parameter(typeof(Hashtable));
|
||||
var assignmentExpression = Expression.Assign(memberAccessExpression, valueParameterExpression);
|
||||
var setFunctionBody = Expression.Block(assignmentExpression, Expression.Constant(true));
|
||||
var setLambdaExpression = Expression.Lambda<Func<LogicalCallContext, Hashtable, bool>>(setFunctionBody, instanceParameterExpression, valueParameterExpression);
|
||||
_setDatastoreFunc = setLambdaExpression.Compile();
|
||||
}
|
||||
|
||||
public static Hashtable GetDatastore(this LogicalCallContext context)
|
||||
=> _getDatastoreFunc(context);
|
||||
|
||||
public static void SetDatastore(this LogicalCallContext context, Hashtable datastore)
|
||||
=> _setDatastoreFunc(context, datastore);
|
||||
}
|
||||
|
||||
internal static class ExecutionContextExtensions
|
||||
{
|
||||
private static readonly Func<ExecutionContext, LogicalCallContext> _getLogicalCallContextFunc;
|
||||
|
||||
static ExecutionContextExtensions()
|
||||
{
|
||||
var logicalCallContextPropertyInfo = typeof(ExecutionContext).GetProperty("LogicalCallContext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var instanceParameterExpression = Expression.Parameter(typeof(ExecutionContext));
|
||||
var memberAccessExpression = Expression.MakeMemberAccess(instanceParameterExpression, logicalCallContextPropertyInfo);
|
||||
var lambdaExpression = Expression.Lambda<Func<ExecutionContext, LogicalCallContext>>(memberAccessExpression, instanceParameterExpression);
|
||||
_getLogicalCallContextFunc = lambdaExpression.Compile();
|
||||
}
|
||||
|
||||
public static LogicalCallContext GetLogicalCallContext(this ExecutionContext executionContext)
|
||||
=> _getLogicalCallContextFunc(executionContext);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dca9e0a0d2088cd47b918c6f54739b95
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
#if NON_UNITY || !NET_STANDARD_2_0
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace MagicOnion.Utils
|
||||
{
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
class DynamicAssembly
|
||||
{
|
||||
readonly object gate = new object();
|
||||
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
readonly string moduleName;
|
||||
#endif
|
||||
readonly AssemblyBuilder assemblyBuilder;
|
||||
readonly ModuleBuilder moduleBuilder;
|
||||
|
||||
// don't expose ModuleBuilder(should use lock)
|
||||
// public ModuleBuilder ModuleBuilder { get { return moduleBuilder; } }
|
||||
|
||||
public DynamicAssembly(string moduleName)
|
||||
{
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
this.moduleName = moduleName;
|
||||
this.assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(moduleName), AssemblyBuilderAccess.RunAndSave);
|
||||
this.moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName, moduleName + ".dll");
|
||||
#else
|
||||
this.assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(moduleName), AssemblyBuilderAccess.Run);
|
||||
this.moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
|
||||
#endif
|
||||
|
||||
// HACK: Allow access to `internal` classes from dynamically generated assembly.
|
||||
// https://www.strathweb.com/2018/10/no-internalvisibleto-no-problem-bypassing-c-visibility-rules-with-roslyn/
|
||||
var ignoreAccessChecksTo = new CustomAttributeBuilder(typeof(IgnoresAccessChecksToAttribute).GetConstructor(new[] {typeof(string)}), new []{ "MagicOnion" });
|
||||
this.assemblyBuilder.SetCustomAttribute(ignoreAccessChecksTo);
|
||||
}
|
||||
|
||||
// requires lock on mono environment(for example, UnityEditor). see: https://github.com/neuecc/MessagePack-CSharp/issues/161
|
||||
|
||||
public TypeBuilder DefineType(string name, TypeAttributes attr)
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return moduleBuilder.DefineType(name, attr);
|
||||
}
|
||||
}
|
||||
|
||||
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return moduleBuilder.DefineType(name, attr, parent);
|
||||
}
|
||||
}
|
||||
|
||||
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
|
||||
{
|
||||
lock (gate)
|
||||
{
|
||||
return moduleBuilder.DefineType(name, attr, parent, interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SAVE_ASSEMBLY
|
||||
|
||||
public AssemblyBuilder Save()
|
||||
{
|
||||
assemblyBuilder.Save(moduleName + ".dll");
|
||||
return assemblyBuilder;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
internal class IgnoresAccessChecksToAttribute : Attribute
|
||||
{
|
||||
public IgnoresAccessChecksToAttribute(string assemblyName)
|
||||
{
|
||||
AssemblyName = assemblyName;
|
||||
}
|
||||
|
||||
public string AssemblyName { get; }
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9d0b2ee1dc31faa43811b3a203a3fc16
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
using System.Text;
|
||||
|
||||
namespace MagicOnion.Utils
|
||||
{
|
||||
public static class FNV1A32
|
||||
{
|
||||
public static int GetHashCode(string str)
|
||||
{
|
||||
return GetHashCode(Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
public static int GetHashCode(byte[] obj)
|
||||
{
|
||||
uint hash = 0;
|
||||
if (obj != null)
|
||||
{
|
||||
hash = 2166136261;
|
||||
for (int i = 0; i < obj.Length; i++)
|
||||
{
|
||||
hash = unchecked((obj[i] ^ hash) * 16777619);
|
||||
}
|
||||
}
|
||||
|
||||
return unchecked((int)hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4257d32e13eee874493c07bf4d4bfc8f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
#if NON_UNITY || !NET_STANDARD_2_0
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace MagicOnion.Utils
|
||||
{
|
||||
// full list of can create optimize helper -> https://github.com/kevin-montrose/Sigil#automated-opcode-choice
|
||||
|
||||
/// <summary>
|
||||
/// Provides optimized generation code and helpers.
|
||||
/// </summary>
|
||||
internal static class ILGeneratorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads the local variable at a specific index onto the evaluation stack.
|
||||
/// </summary>
|
||||
public static void EmitLdloc(this ILGenerator il, int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
il.Emit(OpCodes.Ldloc_0);
|
||||
break;
|
||||
case 1:
|
||||
il.Emit(OpCodes.Ldloc_1);
|
||||
break;
|
||||
case 2:
|
||||
il.Emit(OpCodes.Ldloc_2);
|
||||
break;
|
||||
case 3:
|
||||
il.Emit(OpCodes.Ldloc_3);
|
||||
break;
|
||||
default:
|
||||
if (index <= 255)
|
||||
{
|
||||
il.Emit(OpCodes.Ldloc_S, (byte)index);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Ldloc, (short)index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pops the current value from the top of the evaluation stack and stores it in a the local variable list at a specified index.
|
||||
/// </summary>
|
||||
public static void EmitStloc(this ILGenerator il, int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
il.Emit(OpCodes.Stloc_0);
|
||||
break;
|
||||
case 1:
|
||||
il.Emit(OpCodes.Stloc_1);
|
||||
break;
|
||||
case 2:
|
||||
il.Emit(OpCodes.Stloc_2);
|
||||
break;
|
||||
case 3:
|
||||
il.Emit(OpCodes.Stloc_3);
|
||||
break;
|
||||
default:
|
||||
if (index <= 255)
|
||||
{
|
||||
il.Emit(OpCodes.Stloc_S, (byte)index);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Stloc, (short)index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the address of the local variable at a specific index onto the evaluation statck.
|
||||
/// </summary>
|
||||
public static void EmitLdloca(this ILGenerator il, int index)
|
||||
{
|
||||
if (index <= 255)
|
||||
{
|
||||
il.Emit(OpCodes.Ldloca_S, (byte)index);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Ldloca, (short)index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes a supplied value of type int32 onto the evaluation stack as an int32.
|
||||
/// </summary>
|
||||
public static void EmitLdc_I4(this ILGenerator il, int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case -1:
|
||||
il.Emit(OpCodes.Ldc_I4_M1);
|
||||
break;
|
||||
case 0:
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
break;
|
||||
case 1:
|
||||
il.Emit(OpCodes.Ldc_I4_1);
|
||||
break;
|
||||
case 2:
|
||||
il.Emit(OpCodes.Ldc_I4_2);
|
||||
break;
|
||||
case 3:
|
||||
il.Emit(OpCodes.Ldc_I4_3);
|
||||
break;
|
||||
case 4:
|
||||
il.Emit(OpCodes.Ldc_I4_4);
|
||||
break;
|
||||
case 5:
|
||||
il.Emit(OpCodes.Ldc_I4_5);
|
||||
break;
|
||||
case 6:
|
||||
il.Emit(OpCodes.Ldc_I4_6);
|
||||
break;
|
||||
case 7:
|
||||
il.Emit(OpCodes.Ldc_I4_7);
|
||||
break;
|
||||
case 8:
|
||||
il.Emit(OpCodes.Ldc_I4_8);
|
||||
break;
|
||||
default:
|
||||
if (value >= -128 && value <= 127)
|
||||
{
|
||||
il.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Ldc_I4, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper for Pop op.
|
||||
/// </summary>
|
||||
public static void EmitPop(this ILGenerator il, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
il.Emit(OpCodes.Pop);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EmitNullReturn(this ILGenerator il)
|
||||
{
|
||||
il.Emit(OpCodes.Ldnull);
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
public static void EmitThrowNotimplemented(this ILGenerator il)
|
||||
{
|
||||
il.Emit(OpCodes.Newobj, typeof(System.NotImplementedException).GetConstructor(Type.EmptyTypes));
|
||||
il.Emit(OpCodes.Throw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8d05c89a473ec164b8dc9a918d5c57d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
// Internal, Global.
|
||||
internal static class ReflectionExtensions
|
||||
{
|
||||
public static bool IsNullable(this System.Reflection.TypeInfo type)
|
||||
{
|
||||
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable<>);
|
||||
}
|
||||
|
||||
public static bool IsPublic(this System.Reflection.TypeInfo type)
|
||||
{
|
||||
return type.IsPublic;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 251abd13d00009a44979847381ea168f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
#if NON_UNITY
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Sources;
|
||||
|
||||
namespace MagicOnion.Utils
|
||||
{
|
||||
public class ReservedWhenAllPromise : IValueTaskSource
|
||||
{
|
||||
static class ContinuationSentinel
|
||||
{
|
||||
public static readonly Action<object> AvailableContinuation = _ => { };
|
||||
public static readonly Action<object> CompletedContinuation = _ => { };
|
||||
}
|
||||
|
||||
static readonly ContextCallback execContextCallback = ExecutionContextCallback;
|
||||
static readonly SendOrPostCallback syncContextCallback = SynchronizationContextCallback;
|
||||
|
||||
int completedCount;
|
||||
readonly int resultCount;
|
||||
|
||||
ExceptionDispatchInfo exception;
|
||||
Action<object> continuation = ContinuationSentinel.AvailableContinuation;
|
||||
object state;
|
||||
SynchronizationContext syncContext;
|
||||
ExecutionContext execContext;
|
||||
|
||||
public ReservedWhenAllPromise(int reserveCount)
|
||||
{
|
||||
this.resultCount = reserveCount;
|
||||
}
|
||||
|
||||
public ValueTask AsValueTask() => new ValueTask(this, 0);
|
||||
|
||||
public void Add(ValueTask task)
|
||||
{
|
||||
var awaiter = task.GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
try
|
||||
{
|
||||
awaiter.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ExceptionDispatchInfo.Capture(ex);
|
||||
return;
|
||||
}
|
||||
TryInvokeContinuationWithIncrement();
|
||||
}
|
||||
else
|
||||
{
|
||||
RegisterUnsafeOnCompleted(awaiter);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterUnsafeOnCompleted(ValueTaskAwaiter awaiter)
|
||||
{
|
||||
awaiter.UnsafeOnCompleted(() => ContinuationWithCapture(awaiter));
|
||||
}
|
||||
|
||||
void ContinuationWithCapture(ValueTaskAwaiter awaiter)
|
||||
{
|
||||
try
|
||||
{
|
||||
awaiter.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ExceptionDispatchInfo.Capture(ex);
|
||||
TryInvokeContinuation();
|
||||
return;
|
||||
}
|
||||
TryInvokeContinuationWithIncrement();
|
||||
}
|
||||
|
||||
void TryInvokeContinuationWithIncrement()
|
||||
{
|
||||
if (Interlocked.Increment(ref completedCount) == resultCount)
|
||||
{
|
||||
TryInvokeContinuation();
|
||||
}
|
||||
}
|
||||
|
||||
void TryInvokeContinuation()
|
||||
{
|
||||
var c = Interlocked.Exchange(ref continuation, ContinuationSentinel.CompletedContinuation);
|
||||
if (c != ContinuationSentinel.AvailableContinuation && c != ContinuationSentinel.CompletedContinuation)
|
||||
{
|
||||
var spinWait = new SpinWait();
|
||||
while (state == null) // worst case, state is not set yet so wait.
|
||||
{
|
||||
spinWait.SpinOnce();
|
||||
}
|
||||
|
||||
if (execContext != null)
|
||||
{
|
||||
ExecutionContext.Run(execContext, execContextCallback, Tuple.Create(c, this));
|
||||
}
|
||||
else if (syncContext != null)
|
||||
{
|
||||
syncContext.Post(syncContextCallback, Tuple.Create(c, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
c(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
exception.Throw();
|
||||
}
|
||||
}
|
||||
|
||||
public ValueTaskSourceStatus GetStatus(short token)
|
||||
{
|
||||
return (completedCount == resultCount) ? ValueTaskSourceStatus.Succeeded
|
||||
: (exception != null) ? ((exception.SourceException is OperationCanceledException) ? ValueTaskSourceStatus.Canceled : ValueTaskSourceStatus.Faulted)
|
||||
: ValueTaskSourceStatus.Pending;
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref this.continuation, continuation, ContinuationSentinel.AvailableContinuation) != ContinuationSentinel.AvailableContinuation)
|
||||
{
|
||||
if (this.continuation == ContinuationSentinel.CompletedContinuation)
|
||||
{
|
||||
continuation(state);
|
||||
return;
|
||||
}
|
||||
throw new InvalidOperationException("does not allow multiple await.");
|
||||
}
|
||||
|
||||
this.state = state;
|
||||
if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) == ValueTaskSourceOnCompletedFlags.FlowExecutionContext)
|
||||
{
|
||||
execContext = ExecutionContext.Capture();
|
||||
}
|
||||
if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) == ValueTaskSourceOnCompletedFlags.UseSchedulingContext)
|
||||
{
|
||||
syncContext = SynchronizationContext.Current;
|
||||
}
|
||||
|
||||
if (GetStatus(token) != ValueTaskSourceStatus.Pending)
|
||||
{
|
||||
TryInvokeContinuation();
|
||||
}
|
||||
}
|
||||
|
||||
static void ExecutionContextCallback(object state)
|
||||
{
|
||||
var t = (Tuple<Action<object>, ReservedWhenAllPromise>)state;
|
||||
var self = t.Item2;
|
||||
if (self.syncContext != null)
|
||||
{
|
||||
SynchronizationContextCallback(state);
|
||||
}
|
||||
else
|
||||
{
|
||||
var invokeState = self.state;
|
||||
self.state = null;
|
||||
t.Item1.Invoke(invokeState);
|
||||
}
|
||||
}
|
||||
|
||||
static void SynchronizationContextCallback(object state)
|
||||
{
|
||||
var t = (Tuple<Action<object>, ReservedWhenAllPromise>)state;
|
||||
var self = t.Item2;
|
||||
var invokeState = self.state;
|
||||
self.state = null;
|
||||
t.Item1.Invoke(invokeState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue