コード例 #1
0
        public object DecodeRpcArgument(IRpcChannel channel, IRpcObjectRepository localRepository,
                                        IRpcObjectRepository remoteRepository, IRpcSerializer serializer, RpcArgument argument, Type argumentType)
        {
            switch (argument.Type)
            {
            case RpcType.Builtin:
                if (argument.Value == null || argumentType == typeof(void))
                {
                    return(null);
                }
                if (argumentType.IsAssignableFrom(argument.Value.GetType()))
                {
                    return(argument.Value);
                }

                return(serializer.ChangeType(argument.Value, argumentType));

            case RpcType.Proxy:
                var instanceId = (int)serializer.ChangeType(argument.Value, typeof(int));
                var instance   = localRepository.GetInstance(instanceId);
                if (instance == null)
                {
                    var intfTypes = localRepository.ResolveTypes(argument.TypeId, argumentType);
                    instance = remoteRepository.GetProxyObject(channel, intfTypes, instanceId);
                }
                return(instance);

            case RpcType.Serialized:
                var type = localRepository.ResolveTypes(argument.TypeId, argumentType)[0];
                return(serializer.ChangeType(argument.Value, type));

            case RpcType.ObjectArray:
                var arrayType   = localRepository.ResolveTypes(argument.TypeId, argumentType)[0];
                var elementType = arrayType?.GetElementType() ?? throw new InvalidOperationException();
                var array       = Array.CreateInstance(elementType, (int)argument.Value);

                for (int i = 0; i < array.Length; i++)
                {
                    array.SetValue(DecodeRpcArgument(channel, localRepository, remoteRepository, serializer, argument.ArrayElements[i],
                                                     elementType), i);
                }

                return(array);

            default:
                throw new InvalidDataException();
            }
        }
コード例 #2
0
        private RpcArgument CreateRpcArgument(ITransportChannel channel, IRpcObjectRepository localRepository, object argument, Type argumentType)
        {
            string  typeid = null;
            RpcType type   = RpcType.Proxy;

            RpcArgument[] arrayElements = null;
            if (argument == null ||
                argument is IConvertible)
            {
                type = RpcType.Builtin;
            }
            else if (argument is Array array)
            {
                if ((argument.GetType().GetElementType()?.IsPrimitive ?? false) ||
                    argument.GetType().GetElementType() == typeof(string))
                {
                    type = RpcType.Builtin;
                }
                else
                {
                    type = RpcType.ObjectArray;
                    // make sure we use the correct interface definition as base type (we might get a specific array here)
                    var arrayTemplate = Array.CreateInstance(argumentType.GetElementType(), 0);
                    typeid   = localRepository.CreateTypeId(arrayTemplate);
                    argument = array.Length;
                    var elementType = argumentType.GetElementType();
                    arrayElements = new RpcArgument[array.Length];
                    for (int i = 0; i < array.Length; i++)
                    {
                        arrayElements[i] = CreateRpcArgument(channel, localRepository, array.GetValue(i), elementType);
                    }
                }
            }
            else if (argumentType != typeof(object) &&
                     !argumentType.IsSubclassOf(typeof(Delegate)) &&
                     (argumentType.GetCustomAttribute <SerializableAttribute>() != null ||
                      (argument.GetType().GetCustomAttribute <SerializableAttribute>() != null)))
            {
                type   = RpcType.Serialized;
                typeid = localRepository.CreateTypeId(argument);
            }
            else
            {
                typeid = localRepository.CreateTypeId(argument);

                if (argument is IRpcObjectProxy proxy)
                {
                    /*var instance = localRepository.GetInstance(proxy.LocalInstanceId);
                     * if (instance != null) // todo this check is not necessary
                     * {
                     *  argument = proxy.LocalInstanceId;
                     * }*/
                    argument = proxy.RemoteInstanceId;
                }
                else
                {
                    argument = localRepository.AddInstance(argumentType, argument, channel).InstanceId;
                }
            }

            return(new RpcArgument
            {
                Type = type,
                Value = argument,
                TypeId = typeid,
                ArrayElements = arrayElements
            });
        }