annotate Remoting/RemotingManager.cs @ 49:7e4dae99f919

USBLib: fix unhandled exception in WinUSB shutdown after failure to open device
author Ivo Smits <Ivo@UCIS.nl>
date Mon, 19 Aug 2013 16:56:50 +0200
parents fc3eb8e49ea6
children 5e717aac4c1d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1 ???using System;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
2 using System.Collections.Generic;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
3 using System.IO;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
4 using System.Reflection;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
5 using System.Reflection.Emit;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
6 using System.Runtime.Remoting;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
7 using System.Runtime.Remoting.Messaging;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
8 using System.Runtime.Remoting.Proxies;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
9 using System.Runtime.Serialization;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
10 using System.Threading;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
11 using UCIS.Util;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
12 using SysThreadPool = System.Threading.ThreadPool;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
14 //[assembly: InternalsVisibleToAttribute("UCIS.Remoting.Proxies")]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
15
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
16 namespace UCIS.Remoting {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
17 public class RemotingManager {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
18 Dictionary<UInt32, PendingRemoteCall> pendingCalls = new Dictionary<uint, PendingRemoteCall>();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
19 Dictionary<Thread, UInt32> waitingCallThreads = new Dictionary<Thread, UInt32>();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
20 Boolean Closed = false;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
21
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
22 IDictionary<String, Object> incomingCallContext = new Dictionary<String, Object>();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
23 [ThreadStatic]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
24 static IDictionary<String, Object> currentCallContext;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
25
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
26 public event Action<String> OnDebugLog;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
27 public event Action<Exception> OnErrorLog;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
28
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
29 private void DebugLog(String text, params Object[] args) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
30 if (OnDebugLog != null) OnDebugLog(String.Format(text, args));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
31 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
32 private void ErrorLog(Exception ex) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
33 if (OnErrorLog != null) OnErrorLog(ex);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
34 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
35
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
36 public Object LocalRoot { get; set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
37
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
38 public IDictionary<String, Object> CallContext { get { return incomingCallContext; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
39 public static IDictionary<String, Object> CurrentCallContext { get { return currentCallContext; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
40
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
41 public RemotingManager(PacketStream stream) : this(stream, null) { }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
42 public RemotingManager(PacketStream stream, Object localRoot) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
43 this.stream = stream;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
44 this.LocalRoot = localRoot;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
45 stream.BeginReadPacketFast(ReceiveCallback, null);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
46 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
47
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
48 #region I/O, multiplexing, encoding
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
49 PacketStream stream;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
50 public PacketStream Stream { get { return stream; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
51 int streamIndex = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
52 Dictionary<int, StreamChannel> streamChannels = new Dictionary<int, StreamChannel>();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
53
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
54 class StreamChannel : QueuedPacketStream {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
55 public RemotingManager Manager { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
56 public int StreamID { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
57 public StreamChannel OtherSide { get; set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
58
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
59 public StreamChannel(RemotingManager conn, int sid) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
60 this.Manager = conn;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
61 this.StreamID = sid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
62 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
63
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
64 internal void AddBuffer(Byte[] buffer, int offset, int count) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
65 if (Closed) return;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
66 base.AddReadBufferCopy(buffer, offset, count);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
67 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
68
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
69 public override bool CanRead { get { return !Closed; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
70 public override bool CanWrite { get { return !Closed; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
71
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
72 public override void Flush() { }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
73
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
74 public override void Write(byte[] buffer, int offset, int count) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
75 if (Closed) throw new ObjectDisposedException("BaseStream", "The connection has been closed");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
76 Manager.WriteStreamChannelPacket(StreamID ^ 0x4000, buffer, offset, count);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
77 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
78
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
79 public override void Close() {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
80 StreamChannel other = OtherSide;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
81 MultiplexorClosed();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
82 if (other != null) other.CloseInternal();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
83 lock (Manager.streamChannels) Manager.streamChannels.Remove(StreamID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
84 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
85 public void CloseInternal() {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
86 MultiplexorClosed();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
87 lock (Manager.streamChannels) Manager.streamChannels.Remove(StreamID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
88 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
89 internal void MultiplexorClosed() {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
90 base.Close();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
91 OtherSide = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
92 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
93 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
94
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
95 private void ReceiveCallback(IAsyncResult ar) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
96 if (ar.CompletedSynchronously) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
97 SysThreadPool.QueueUserWorkItem(ReceiveCallbackA, ar);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
98 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
99 ReceiveCallbackB(ar);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
100 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
101 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
102 private void ReceiveCallbackA(Object state) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
103 ReceiveCallbackB((IAsyncResult)state);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
104 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
105 private void ReceiveCallbackB(IAsyncResult ar) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
106 try {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
107 ArraySegment<Byte> packet = stream.EndReadPacketFast(ar);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
108 Byte[] array = packet.Array;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
109 if (packet.Count < 2) throw new ArgumentOutOfRangeException("packet.Count", "Packet is too small");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
110 int offset = packet.Offset;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
111 int sid = (array[offset + 0] << 8) | (array[offset + 1] << 0);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
112 if ((sid & 0x8000) != 0) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
113 StreamChannel substr;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
114 if (streamChannels.TryGetValue(sid, out substr)) substr.AddBuffer(array, offset + 2, packet.Count - 2);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
115 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
116 stream.BeginReadPacketFast(ReceiveCallback, null);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
117 if (sid == 0) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
118 Object obj;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
119 using (MemoryStream ms = new MemoryStream(packet.Array, packet.Offset + 2, packet.Count - 2, false)) obj = Deserialize(ms);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
120 ReceiveObject(obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
121 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
122 } catch (Exception ex) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
123 Closed = true;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
124 stream.Close();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
125 lock (ObjectReferencesByID) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
126 ObjectReferencesByID.Clear();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
127 RemoteObjectReferences.Clear();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
128 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
129 lock (pendingCalls) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
130 foreach (PendingRemoteCall call in pendingCalls.Values) call.SetError(new InvalidOperationException("The connection has been closed"));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
131 pendingCalls.Clear();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
132 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
133 lock (streamChannels) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
134 foreach (StreamChannel s in streamChannels.Values) s.MultiplexorClosed();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
135 streamChannels.Clear();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
136 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
137 ErrorLog(ex);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
138 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
139 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
140 private void SendObject(Object obj) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
141 if (Closed) throw new ObjectDisposedException("RemotingManager", "The connection has been closed");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
142 using (MemoryStream ms = new MemoryStream()) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
143 ms.WriteByte(0);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
144 ms.WriteByte(0);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
145 Serialize(ms, obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
146 lock (stream) ms.WriteTo(stream);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
147 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
148 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
149
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
150 private void WriteStreamChannelPacket(int sid, Byte[] buffer, int offset, int count) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
151 Byte[] store = new Byte[count + 2];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
152 store[0] = (Byte)(sid >> 8);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
153 store[1] = (Byte)(sid >> 0);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
154 Buffer.BlockCopy(buffer, offset, store, 2, count);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
155 lock (stream) stream.Write(store, 0, store.Length);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
156 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
157
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
158 public PacketStream GetStreamPair(out PacketStream remote) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
159 StreamChannel stream;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
160 int sid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
161 lock (streamChannels) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
162 if (Closed) throw new ObjectDisposedException("BaseStream", "Reading from the base stream failed");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
163 while (true) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
164 sid = Interlocked.Increment(ref streamIndex);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
165 if ((sid & 0xc000) != 0) streamIndex = sid = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
166 sid |= 0x8000;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
167 if (!streamChannels.ContainsKey(sid)) break;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
168 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
169 stream = new StreamChannel(this, sid);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
170 streamChannels.Add(sid, stream);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
171 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
172 stream.OtherSide = (StreamChannel)SyncCall(new CreateStreamRequest() { StreamObject = stream, StreamID = sid | 0x4000 });
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
173 remote = stream.OtherSide;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
174 return stream;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
175 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
176 #endregion
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
177
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
178 #region Incoming call processing
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
179 private void ReceiveObject(Object obj) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
180 if (obj is ReferenceReleaseRequest) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
181 ReferenceReleaseRequest req = (ReferenceReleaseRequest)obj;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
182 lock (ObjectReferencesByID) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
183 RemoteObjectReference objref = (RemoteObjectReference)ObjectReferencesByID[req.ObjectID];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
184 if (objref.Release(req.ReferenceCount) == 0) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
185 ObjectReferencesByID.Remove(objref.ID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
186 RemoteObjectReferences.Remove(objref);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
187 DebugLog("Release remoted object {0} with reference count {1}; {2} objects referenced", objref.ID, req.ReferenceCount, RemoteObjectReferences.Count);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
188 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
189 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
190 } else if (obj is SynchronousCall) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
191 SynchronousCall sc = (SynchronousCall)obj;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
192 if (sc.IsResult) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
193 PendingRemoteCall call;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
194 lock (pendingCalls) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
195 call = pendingCalls[sc.CallID];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
196 pendingCalls.Remove(call.ID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
197 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
198 call.SetResult(sc.Data);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
199 } else if (sc.HasPreviousCallID) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
200 PendingRemoteCall call;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
201 lock (pendingCalls) call = pendingCalls[sc.PreviousCallID];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
202 if (!call.SetNextCall(sc)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
203 ProcessRemoteCallRequest(sc);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
204 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
205 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
206 ProcessRemoteCallRequest(sc);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
207 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
208 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
209 throw new InvalidDataException("Unexpected object type");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
210 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
211 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
212
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
213 private void ProcessRemoteCallRequest(SynchronousCall call) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
214 UInt32 prevcallid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
215 Boolean hasprevcallid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
216 Thread currentThread = Thread.CurrentThread;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
217 lock (waitingCallThreads) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
218 hasprevcallid = waitingCallThreads.TryGetValue(currentThread, out prevcallid);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
219 waitingCallThreads[currentThread] = call.CallID;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
220 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
221 IDictionary<String, Object> prevCallContext = currentCallContext;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
222 currentCallContext = incomingCallContext;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
223 try {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
224 call.Data = ProcessRemoteCallRequestA(call.Data);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
225 } finally {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
226 currentCallContext = prevCallContext;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
227 lock (waitingCallThreads) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
228 if (hasprevcallid) waitingCallThreads[currentThread] = prevcallid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
229 else waitingCallThreads.Remove(currentThread);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
230 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
231 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
232 call.IsResult = true;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
233 SendObject(call);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
234 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
235
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
236 private Object FixReturnType(Object value, Type expectedType) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
237 if (value == null) return value;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
238 Type valueType = value.GetType();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
239 if (valueType != expectedType) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
240 if (valueType.IsArray) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
241 Array retarray = value as Array;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
242 if (retarray != null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
243 if (!valueType.GetElementType().IsPublic && retarray.Rank == 1 &&
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
244 (
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
245 expectedType.IsArray ||
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
246 (expectedType.IsGenericType && (expectedType.GetGenericTypeDefinition() == typeof(IEnumerable<>) || expectedType.GetGenericTypeDefinition() == typeof(ICollection<>) || expectedType.GetGenericTypeDefinition() == typeof(IList<>)))
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
247 )
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
248 ) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
249 Type btype = expectedType.IsArray ? expectedType.GetElementType() : expectedType.GetGenericArguments()[0];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
250 Array r = Array.CreateInstance(btype, retarray.Length);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
251 retarray.CopyTo(r, 0);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
252 value = r;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
253 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
254 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
255 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
256 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
257 return value;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
258 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
259 private Object ProcessRemoteMethodCallRequestA(Object ret) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
260 if (ret is DelegateCallRequest) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
261 DelegateCallRequest call = (DelegateCallRequest)ret;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
262 Object target = call.Delegate;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
263 DebugLog("Remote delegate call on {0}", target);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
264 if (ReferenceEquals(target, null)) throw new NullReferenceException("target");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
265 if (!(target is Delegate)) throw new InvalidCastException("target");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
266 Object[] args = call.Arguments;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
267 return ((Delegate)target).DynamicInvoke(args);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
268 } else if (ret is MethodCallRequest) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
269 MethodCallRequest call = (MethodCallRequest)ret;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
270 Object target = call.Object;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
271 if (ReferenceEquals(target, null)) throw new NullReferenceException("target");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
272 Type intf = call.Type ?? target.GetType();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
273 DebugLog("Remote call {0}.{1} on {2}", intf.FullName, call.MethodName, target);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
274 if (!intf.IsInstanceOfType(target)) throw new InvalidCastException("target");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
275 MethodInfo meth;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
276 if (call.MethodSignature != null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
277 meth = intf.GetMethod(call.MethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, call.MethodSignature, null);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
278 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
279 meth = intf.GetMethod(call.MethodName, BindingFlags.Instance | BindingFlags.Public);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
280 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
281 if (meth == null) throw new NullReferenceException("method");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
282 Object[] args = call.Arguments;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
283 Object retval;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
284 if (meth.Name == "GetType" && meth == typeof(Object).GetMethod("GetType", Type.EmptyTypes)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
285 if (target.GetType().IsPublic) retval = target.GetType();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
286 else retval = intf;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
287 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
288 retval = meth.Invoke(target, args);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
289 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
290 //Todo: causes lots of redundant data transfers, do something about it!
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
291 /*Object[] rargs = new Object[0];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
292 for (int i = 0; i < args.Length; i++) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
293 if (args[i] == null) continue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
294 if (args[i].GetType().IsArray) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
295 Array.Resize(ref rargs, i + 1);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
296 rargs[i] = args[i];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
297 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
298 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
299 resp.ReturnArguments = rargs;*/
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
300 return FixReturnType(retval, meth.ReturnType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
301 } else if (ret is PropertyAccessRequest) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
302 PropertyAccessRequest call = (PropertyAccessRequest)ret;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
303 Object target = call.Object;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
304 if (ReferenceEquals(target, null)) throw new NullReferenceException("target");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
305 Type intf = call.Type ?? target.GetType();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
306 DebugLog("Remote property access {0}.{1} on {2}", intf.FullName, call.PropertyName, target);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
307 if (!intf.IsInstanceOfType(target)) throw new InvalidCastException("target");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
308 PropertyInfo meth = intf.GetProperty(call.PropertyName, BindingFlags.Instance | BindingFlags.Public);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
309 if (meth == null) throw new NullReferenceException("property");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
310 if (call.SetValue) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
311 meth.SetValue(target, call.Value, null);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
312 return null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
313 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
314 return FixReturnType(meth.GetValue(target, null), meth.PropertyType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
315 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
316 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
317 throw new InvalidDataException("Unexpected object type");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
318 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
319 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
320 private Object ProcessRemoteCallRequestA(Object ret) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
321 if (ret is DelegateCallRequest || ret is MethodCallRequest || ret is PropertyAccessRequest) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
322 MethodCallResponse resp = new MethodCallResponse();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
323 try {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
324 resp.ReturnValue = ProcessRemoteMethodCallRequestA(ret);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
325 } catch (Exception ex) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
326 resp.Exception = ex;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
327 ErrorLog(ex);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
328 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
329 return resp;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
330 } else if (ret is GetRootRequest) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
331 DebugLog("Remote root request");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
332 return LocalRoot;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
333 } else if (ret is ObjectCanCastToRequest) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
334 ObjectCanCastToRequest ctr = (ObjectCanCastToRequest)ret;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
335 Type intf = ctr.Type;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
336 Object target = ctr.Object;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
337 DebugLog("Remote type check for {0} on {1}", intf.Name, target);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
338 return intf != null && intf.IsInstanceOfType(target);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
339 } else if (ret is CreateStreamRequest) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
340 CreateStreamRequest csr = (CreateStreamRequest)ret;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
341 StreamChannel ss = new StreamChannel(this, csr.StreamID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
342 ss.OtherSide = csr.StreamObject;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
343 lock (streamChannels) streamChannels.Add(csr.StreamID, ss);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
344 return ss;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
345 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
346 throw new InvalidDataException("Unexpected object type");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
347 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
348 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
349 #endregion
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
350
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
351 #region Outgoing calls
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
352 UInt32 callID = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
353 private UInt32 AllocatePendingCallID(PendingRemoteCall call) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
354 UInt32 cid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
355 lock (pendingCalls) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
356 while (true) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
357 cid = ++callID;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
358 if (!pendingCalls.ContainsKey(cid)) break;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
359 Monitor.Wait(pendingCalls);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
360 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
361 call.ID = cid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
362 pendingCalls.Add(cid, call);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
363 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
364 return cid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
365 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
366 private Object SyncCall(Object req) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
367 UInt32 previousCall;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
368 Boolean hasPreviousCall;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
369 lock (waitingCallThreads) hasPreviousCall = waitingCallThreads.TryGetValue(Thread.CurrentThread, out previousCall);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
370 PendingRemoteCall pending = new PendingRemoteCall() { Completed = false, WaitHandle = new ManualResetEvent(false), CallData = req };
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
371 AllocatePendingCallID(pending);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
372 SynchronousCall call = new SynchronousCall() { IsResult = false, CallID = pending.ID, Data = req, HasPreviousCallID = false };
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
373 if (hasPreviousCall) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
374 call.HasPreviousCallID = true;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
375 call.PreviousCallID = previousCall;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
376 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
377 SendObject(call);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
378 while (true) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
379 pending.WaitHandle.WaitOne();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
380 if (pending.Completed) break;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
381 pending.WaitHandle.Reset();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
382 if (pending.NextCall == null) throw new InvalidOperationException("Operation did not complete");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
383 SynchronousCall sc = pending.NextCall.Value;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
384 pending.NextCall = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
385 ProcessRemoteCallRequest(sc);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
386 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
387 pending.WaitHandle.Close();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
388 if (pending.Error != null) throw pending.Error;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
389 return pending.Response;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
390 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
391 private void AsyncCall(Object req) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
392 UInt32 cid = AllocatePendingCallID(new PendingRemoteCall() { Completed = false, CallData = req });
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
393 SendObject(new SynchronousCall() { IsResult = false, CallID = cid, Data = req, HasPreviousCallID = false });
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
394 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
395
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
396 public Object RemoteRoot {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
397 get {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
398 return SyncCall(new GetRootRequest());
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
399 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
400 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
401
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
402 public static void AsyncCall(Delegate f, params Object[] args) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
403 IProxyBase proxy;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
404 if ((proxy = GetRealProxyForObject(f)) != null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
405 proxy.Manager.AsyncCall(new DelegateCallRequest() { Delegate = proxy, Arguments = args });
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
406 } else if ((proxy = GetRealProxyForObject(f.Target)) != null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
407 MethodCallRequest call = new MethodCallRequest() { Object = proxy, Type = f.Method.DeclaringType, MethodName = f.Method.Name, Arguments = args };
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
408 call.MethodSignature = ConvertMethodParameterTypeArray(f.Method);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
409 proxy.Manager.AsyncCall(call);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
410 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
411 throw new InvalidOperationException("Delegate is not a proxy for a remote object");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
412 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
413 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
414
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
415 private static Type[] ConvertMethodParameterTypeArray(MethodInfo method) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
416 ParameterInfo[] parameters = method.GetParameters();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
417 Type[] types = new Type[parameters.Length];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
418 for (int i = 0; i < types.Length; i++) types[i] = parameters[i].ParameterType;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
419 return types;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
420 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
421 private void ProxyCallCheckReturnType(Object value, Type type) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
422 if (type == typeof(void)) return;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
423 if (type.IsInstanceOfType(value)) return;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
424 if (value == null && !type.IsValueType) return;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
425 throw new InvalidCastException("Type returned by remote procedure does not match expected type.");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
426 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
427 private void ProxyCallFixReturnArguments(Object[] args, Object[] rargs) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
428 if (rargs == null) return;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
429 for (int i = 0; i < rargs.Length; i++) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
430 if (rargs[i] == null) continue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
431 if (args[i] != null && args[i].GetType().IsArray) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
432 ((Array)rargs[i]).CopyTo((Array)args[i], 0);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
433 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
434 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
435 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
436 private Object ProxyMakeCallDelegate(DelegateProxy obj, Object[] args) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
437 DelegateCallRequest call = new DelegateCallRequest() { Delegate = obj, Arguments = args };
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
438 MethodCallResponse resp = (MethodCallResponse)SyncCall(call);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
439 if (resp.Exception != null) throw new Exception("Remote exception", resp.Exception);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
440 ProxyCallFixReturnArguments(args, resp.ReturnArguments);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
441 ProxyCallCheckReturnType(resp.ReturnValue, obj.MethodSignature.ReturnType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
442 return resp.ReturnValue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
443 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
444 private Object ProxyMakeCall(IProxyBase obj, MethodInfo method, Object[] args) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
445 /*if (args.Length == 1 && method.ReturnType == typeof(void) && args[0] != null && args[0] is Delegate) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
446 foreach (EventInfo ei in type.GetEvents()) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
447 if (ei.EventHandlerType.IsInstanceOfType(args[0])) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
448 if (method == ei.GetAddMethod()) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
449 Console.WriteLine("ADD EVENT");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
450 } else if (method == ei.GetRemoveMethod()) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
451 Console.WriteLine("REMOVE EVENT");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
452 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
453 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
454 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
455 }*/
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
456 MethodCallRequest call = new MethodCallRequest() { Object = obj, Type = method.DeclaringType, MethodName = method.Name, Arguments = args };
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
457 call.MethodSignature = ConvertMethodParameterTypeArray(method);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
458 MethodCallResponse resp = (MethodCallResponse)SyncCall(call);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
459 if (resp.Exception != null) throw new Exception("Remote exception", resp.Exception);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
460 ProxyCallFixReturnArguments(args, resp.ReturnArguments);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
461 ProxyCallCheckReturnType(resp.ReturnValue, method.ReturnType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
462 return resp.ReturnValue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
463 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
464 private Boolean ProxyCanCastTo(IProxyBase obj, Type type) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
465 return (Boolean)SyncCall(new ObjectCanCastToRequest() { Object = obj, Type = type });
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
466 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
467 private void ProxyReleaseObject(ProxyObjectReference objref) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
468 if (objref == null) return;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
469 ProxyReleaseObject(objref, objref.RefCnt);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
470 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
471 private void ProxyReleaseObject(ProxyObjectReference objref, int refcnt) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
472 lock (ObjectReferencesByID) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
473 int newrefcnt = objref.Release(refcnt);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
474 IObjectReferenceBase regobjref;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
475 if (newrefcnt <= 0 && ObjectReferencesByID.TryGetValue(objref.ID, out regobjref) && objref == regobjref) ObjectReferencesByID.Remove(objref.ID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
476 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
477 try {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
478 if (Closed) return;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
479 SendObject(new ReferenceReleaseRequest() { ObjectID = objref.RemoteID, ReferenceCount = refcnt });
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
480 } catch (Exception) { } //Assume the exception happened because the connection is closed. Otherwise memory leak...
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
481 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
482
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
483 class PendingRemoteCall {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
484 public UInt32 ID = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
485 public ManualResetEvent WaitHandle = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
486 public Object Response = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
487 public Exception Error = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
488 public Boolean Completed = false;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
489 public SynchronousCall? NextCall = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
490 public Object CallData = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
491
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
492 public void SetError(Exception error) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
493 this.Error = error;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
494 Completed = true;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
495 if (WaitHandle != null) WaitHandle.Set();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
496 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
497 public void SetResult(Object result) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
498 this.Response = result;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
499 Completed = true;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
500 if (WaitHandle != null) WaitHandle.Set();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
501 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
502 public Boolean SetNextCall(SynchronousCall nextcall) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
503 if (WaitHandle == null) return false;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
504 this.NextCall = nextcall;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
505 WaitHandle.Set();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
506 return true;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
507 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
508 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
509 #endregion
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
510
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
511 #region Object serialization support
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
512 private void Serialize(Stream stream, Object obj) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
513 BinaryWriter writer = new BinaryWriter(stream);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
514 Serialize(writer, obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
515 writer.Flush();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
516 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
517 private void Serialize(BinaryWriter writer, Object obj) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
518 if (ReferenceEquals(obj, null)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
519 writer.Write((Byte)0);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
520 } else if (GetRealProxyForObject(obj) != null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
521 GetObjectData(obj, writer);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
522 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
523 Type type = obj.GetType();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
524 if (type == typeof(Boolean)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
525 writer.Write((Byte)1);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
526 writer.Write((Boolean)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
527 } else if (type == typeof(Byte)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
528 writer.Write((Byte)2);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
529 writer.Write((Byte)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
530 } else if (type == typeof(Char)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
531 writer.Write((Byte)3);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
532 writer.Write((Int16)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
533 } else if (type == typeof(Decimal)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
534 writer.Write((Byte)4);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
535 writer.Write((Decimal)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
536 } else if (type == typeof(Double)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
537 writer.Write((Byte)5);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
538 writer.Write((Double)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
539 } else if (type == typeof(Int16)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
540 writer.Write((Byte)6);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
541 writer.Write((Int16)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
542 } else if (type == typeof(Int32)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
543 writer.Write((Byte)7);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
544 writer.Write((Int32)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
545 } else if (type == typeof(Int64)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
546 writer.Write((Byte)8);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
547 writer.Write((Int64)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
548 } else if (type == typeof(SByte)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
549 writer.Write((Byte)9);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
550 writer.Write((SByte)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
551 } else if (type == typeof(Single)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
552 writer.Write((Byte)10);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
553 writer.Write((Single)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
554 } else if (type == typeof(String)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
555 writer.Write((Byte)11);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
556 writer.Write((String)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
557 } else if (type == typeof(UInt16)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
558 writer.Write((Byte)12);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
559 writer.Write((UInt16)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
560 } else if (type == typeof(UInt32)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
561 writer.Write((Byte)13);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
562 writer.Write((UInt32)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
563 } else if (type == typeof(UInt64)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
564 writer.Write((Byte)14);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
565 writer.Write((UInt64)obj);
14
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
566 } else if (type == typeof(DateTime)) {
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
567 writer.Write((Byte)32);
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
568 writer.Write((Int64)((DateTime)obj).ToBinary());
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
569 } else if (type.IsSubclassOf(typeof(Type))) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
570 writer.Write((Byte)165);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
571 SerializeType(writer, (Type)obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
572 } else if (type.IsArray) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
573 writer.Write((Byte)164);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
574 Array arr = (Array)obj;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
575 writer.Write((int)arr.Length);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
576 SerializeType(writer, type.GetElementType());
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
577 for (int i = 0; i < arr.Length; i++) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
578 Serialize(writer, arr.GetValue(i));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
579 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
580 } else if (type.IsPrimitive) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
581 throw new NotSupportedException();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
582 } else if (typeof(Delegate).IsAssignableFrom(type) || type.IsMarshalByRef) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
583 GetObjectData(obj, writer);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
584 } else if (obj is ISerializable) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
585 SerializationInfo si = new SerializationInfo(type, new FormatterConverter());
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
586 ((ISerializable)obj).GetObjectData(si, new StreamingContext(StreamingContextStates.All));
14
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
587 writer.Write((Byte)128);
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
588 SerializeType(writer, Type.GetType(si.FullTypeName + "," + si.AssemblyName));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
589 writer.Write((int)si.MemberCount);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
590 foreach (SerializationEntry se in si) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
591 writer.Write(se.Name);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
592 Serialize(writer, se.Value);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
593 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
594 } else if (type.IsSerializable) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
595 MemberInfo[] members = FormatterServices.GetSerializableMembers(type);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
596 Object[] values = FormatterServices.GetObjectData(obj, members);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
597 writer.Write((Byte)128);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
598 SerializeType(writer, type);
14
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
599 writer.Write((int)members.Length);
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
600 for (int i = 0; i < members.Length; i++) {
14
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
601 writer.Write(members[i].Name);
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
602 Serialize(writer, values[i]);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
603 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
604 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
605 GetObjectData(obj, writer);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
606 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
607 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
608 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
609 private void SerializeType(BinaryWriter writer, Type t) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
610 writer.Write(t.FullName);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
611 writer.Write(t.Assembly.FullName);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
612 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
613 private Object Deserialize(Stream stream) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
614 BinaryReader reader = new BinaryReader(stream);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
615 return Deserialize(reader);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
616 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
617 private Object Deserialize(BinaryReader reader) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
618 Byte t = reader.ReadByte();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
619 if (t == 0) return null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
620 if (t == 1) return reader.ReadBoolean();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
621 if (t == 2) return reader.ReadByte();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
622 if (t == 3) return (Char)reader.ReadInt16();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
623 if (t == 4) return reader.ReadDecimal();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
624 if (t == 5) return reader.ReadDouble();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
625 if (t == 6) return reader.ReadInt16();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
626 if (t == 7) return reader.ReadInt32();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
627 if (t == 8) return reader.ReadInt64();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
628 if (t == 9) return reader.ReadSByte();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
629 if (t == 10) return reader.ReadSingle();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
630 if (t == 11) return reader.ReadString();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
631 if (t == 12) return reader.ReadUInt16();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
632 if (t == 13) return reader.ReadUInt32();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
633 if (t == 14) return reader.ReadUInt64();
14
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
634 if (t == 32) return DateTime.FromBinary(reader.ReadInt64());
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
635 if (t == 128) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
636 Type type = DeserializeType(reader);
14
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
637 int cnt = reader.ReadInt32();
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
638 Object inst;
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
639 StreamingContext sc = new StreamingContext(StreamingContextStates.All);
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
640 if (typeof(ISerializable).IsAssignableFrom(type) && type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(SerializationInfo), typeof(StreamingContext) }, null) != null) {
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
641 SerializationInfo si = new SerializationInfo(type, new FormatterConverter());
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
642 for (int i = 0; i < cnt; i++) {
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
643 String name = reader.ReadString();
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
644 Object value = Deserialize(reader);
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
645 si.AddValue(name, value);
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
646 }
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
647 inst = Activator.CreateInstance(type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Object[] { si, sc }, null);
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
648 } else if (type.IsSerializable) {
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
649 inst = FormatterServices.GetUninitializedObject(type);
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
650 List<MemberInfo> members = new List<MemberInfo>();
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
651 List<Object> values = new List<object>();
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
652 for (int i = 0; i < cnt; i++) {
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
653 String mname = reader.ReadString();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
654 Object value = Deserialize(reader);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
655 MemberInfo[] mms = type.GetMember(mname, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
656 if (mms.Length != 1) throw new InvalidOperationException();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
657 members.Add(mms[0]);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
658 values.Add(value);
14
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
659 }
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
660 FormatterServices.PopulateObjectMembers(inst, members.ToArray(), values.ToArray());
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
661 } else {
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
662 throw new InvalidOperationException("Type " + type.Name + " is not serializable");
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
663 }
14
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
664 IObjectReference objref = inst as IObjectReference;
fc3eb8e49ea6 Remoting: fixes for linux/mono
Ivo Smits <Ivo@UCIS.nl>
parents: 13
diff changeset
665 if (objref != null) inst = objref.GetRealObject(sc);
13
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
666 return inst;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
667 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
668 if (t == 129 || t == 130 || t == 131) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
669 return SetObjectData(t, reader);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
670 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
671 if (t == 164) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
672 int len = reader.ReadInt32();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
673 Type type = DeserializeType(reader); Array arr = Array.CreateInstance(type, len);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
674 for (int i = 0; i < len; i++) arr.SetValue(Deserialize(reader), i);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
675 return arr;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
676 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
677 if (t == 165) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
678 return DeserializeType(reader);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
679 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
680 throw new NotSupportedException();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
681 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
682 private Type DeserializeType(BinaryReader reader) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
683 String name = reader.ReadString();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
684 String aname = reader.ReadString();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
685 Type t = Type.GetType(name + ", " + aname, false);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
686 if (t != null) return t;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
687 foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
688 t = assembly.GetType(name, false);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
689 if (t != null) return t;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
690 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
691 return t;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
692 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
693
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
694 Dictionary<UInt32, IObjectReferenceBase> ObjectReferencesByID = new Dictionary<uint, IObjectReferenceBase>();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
695 List<RemoteObjectReference> RemoteObjectReferences = new List<RemoteObjectReference>();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
696 uint remoteReferenceIndex = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
697 void GetObjectData(object obj, BinaryWriter w) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
698 IObjectReferenceBase rref = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
699 IProxyBase proxy = GetRealProxyForObject(obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
700 if (proxy != null && proxy.Manager == this) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
701 rref = proxy.ObjectReference;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
702 w.Write((Byte)131);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
703 w.Write((UInt32)rref.RemoteID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
704 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
705 Boolean isDelegate = obj is Delegate;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
706 lock (ObjectReferencesByID) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
707 foreach (IObjectReferenceBase objref in RemoteObjectReferences) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
708 Object other = objref.Target;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
709 if (ReferenceEquals(other, obj) || (isDelegate && Delegate.Equals(other, obj))) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
710 rref = objref;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
711 break;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
712 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
713 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
714 if (rref == null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
715 UInt32 objid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
716 lock (ObjectReferencesByID) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
717 while (true) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
718 remoteReferenceIndex++;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
719 objid = remoteReferenceIndex;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
720 if ((objid & 0x80000000) != 0) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
721 remoteReferenceIndex = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
722 continue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
723 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
724 if (!ObjectReferencesByID.ContainsKey(objid)) break;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
725 Monitor.Wait(ObjectReferencesByID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
726 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
727 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
728 rref = new RemoteObjectReference(objid, obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
729 ObjectReferencesByID.Add(objid, rref);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
730 RemoteObjectReferences.Add((RemoteObjectReference)rref);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
731 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
732 rref.AddRef();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
733 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
734 if (isDelegate) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
735 w.Write((Byte)130);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
736 w.Write((UInt32)rref.RemoteID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
737 SerializeType(w, obj.GetType());
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
738 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
739 w.Write((Byte)129);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
740 w.Write((UInt32)rref.RemoteID);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
741 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
742 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
743 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
744 object SetObjectData(Byte t, BinaryReader r) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
745 UInt32 objid = r.ReadUInt32();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
746 Type deltype = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
747 if (t == 130) deltype = DeserializeType(r);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
748 lock (ObjectReferencesByID) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
749 Object target = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
750 IObjectReferenceBase rref;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
751 if (ObjectReferencesByID.TryGetValue(objid, out rref)) target = rref.Target;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
752 if (t == 131) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
753 if (target == null) throw new InvalidOperationException("Object not found");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
754 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
755 if (target == null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
756 if ((objid & 0x80000000) == 0) throw new InvalidOperationException("The Object ID is invalid");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
757 IProxyBase proxy;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
758 if (t == 130) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
759 proxy = CreateDelegateProxy(objid, deltype);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
760 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
761 String[] iftypes = null; //(String[])info.GetValue("InterfaceTypes", typeof(String[]));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
762 proxy = CreateObjectProxy(objid, iftypes);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
763 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
764 rref = proxy.ObjectReference;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
765 ObjectReferencesByID[objid] = rref;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
766 target = proxy.GetTransparentProxy();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
767 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
768 rref.AddRef();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
769 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
770 return target;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
771 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
772 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
773 #endregion
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
774
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
775 #region RPC messages
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
776 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
777 struct SynchronousCall {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
778 public UInt32 CallID;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
779 public Boolean IsResult;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
780 public Object Data;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
781 public Boolean HasPreviousCallID;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
782 public UInt32 PreviousCallID;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
783 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
784
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
785 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
786 struct MethodCallRequest {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
787 public Object Object;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
788 public Type Type;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
789 public String MethodName;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
790 public Type[] MethodSignature;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
791 public Object[] Arguments;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
792 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
793 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
794 struct MethodCallResponse {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
795 public Exception Exception;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
796 public Object ReturnValue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
797 public Object[] ReturnArguments;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
798 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
799 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
800 struct PropertyAccessRequest {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
801 public Object Object;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
802 public Type Type;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
803 public String PropertyName;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
804 public Boolean SetValue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
805 public Object Value;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
806 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
807 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
808 struct ReferenceReleaseRequest {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
809 public UInt32 ObjectID;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
810 public Int32 ReferenceCount;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
811 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
812 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
813 struct GetRootRequest {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
814 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
815 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
816 struct ObjectCanCastToRequest {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
817 public Object Object;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
818 public Type Type;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
819 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
820 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
821 struct CreateStreamRequest {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
822 public StreamChannel StreamObject;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
823 public int StreamID;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
824 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
825 [Serializable]
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
826 struct DelegateCallRequest {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
827 public Object Delegate;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
828 public Object[] Arguments;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
829 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
830 #endregion
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
831
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
832 #region Proxy magic
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
833 static IProxyBase GetRealProxyForObject(Object obj) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
834 if (RemotingServices.IsTransparentProxy(obj)) return RemotingServices.GetRealProxy(obj) as FWProxy;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
835 IProxyBase obj_IProxyBase = obj as IProxyBase;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
836 if (obj_IProxyBase != null) return obj_IProxyBase;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
837 Delegate obj_Delegate = obj as Delegate;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
838 if (obj_Delegate != null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
839 DelegateProxy pb = obj_Delegate.Target as DelegateProxy;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
840 if (pb != null) return pb;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
841 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
842 return null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
843 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
844 public static RemotingManager GetManagerForObjectProxy(Object obj) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
845 IProxyBase prox = GetRealProxyForObject(obj);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
846 if (prox == null) return null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
847 return prox.Manager;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
848 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
849
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
850 interface IObjectReferenceBase {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
851 UInt32 ID { get; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
852 Object Target { get; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
853 int AddRef();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
854 int RefCnt { get; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
855 Boolean IsLocal { get; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
856 UInt32 RemoteID { get; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
857 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
858
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
859 class RemoteObjectReference : IObjectReferenceBase {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
860 int refcnt = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
861 public UInt32 ID { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
862 public Object Target { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
863 public int RefCnt { get { return refcnt; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
864 public int AddRef() { return Interlocked.Increment(ref refcnt); }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
865 public int Release(int count) { return Interlocked.Add(ref refcnt, -count); }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
866 public Boolean IsLocal { get { return true; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
867 public UInt32 RemoteID { get { return ID | 0x80000000; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
868 public RemoteObjectReference(UInt32 id, Object obj) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
869 if ((id & 0x80000000) != 0) throw new InvalidOperationException("The Object ID is invalid");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
870 this.ID = id;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
871 this.Target = obj;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
872 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
873 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
874
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
875 interface IProxyBase {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
876 RemotingManager Manager { get; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
877 UInt32 ID { get; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
878 ProxyObjectReference ObjectReference { get; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
879 Object GetTransparentProxy();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
880 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
881 class ProxyObjectReference : IObjectReferenceBase {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
882 int refcnt = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
883 WeakReference targetref;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
884 public UInt32 ID { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
885 public RemotingManager Manager { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
886 public Object Target {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
887 get {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
888 IProxyBase proxy = this.Proxy;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
889 if (proxy == null) return null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
890 return proxy.GetTransparentProxy();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
891 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
892 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
893 public IProxyBase Proxy {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
894 get {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
895 if (targetref == null) return null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
896 return (IProxyBase)targetref.Target;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
897 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
898 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
899 public int RefCnt { get { return refcnt; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
900 public int AddRef() {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
901 int newcnt = Interlocked.Increment(ref refcnt);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
902 if (newcnt > 10000 && Interlocked.CompareExchange(ref refcnt, 1, newcnt) == newcnt) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
903 Manager.ProxyReleaseObject(this, newcnt - 1);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
904 newcnt = 1;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
905 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
906 return newcnt;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
907 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
908 public int Release(int count) { return Interlocked.Add(ref refcnt, -count); }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
909 public Boolean IsLocal { get { return false; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
910 public UInt32 RemoteID { get { return ID & 0x7FFFFFFF; } }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
911 public ProxyObjectReference(IProxyBase proxy) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
912 this.Manager = proxy.Manager;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
913 this.ID = proxy.ID;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
914 if ((ID & 0x80000000) == 0) throw new InvalidOperationException("The Object ID is invalid");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
915 targetref = new WeakReference(proxy);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
916 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
917 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
918 class DelegateProxy : IProxyBase {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
919 public ProxyObjectReference ObjectReference { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
920 public RemotingManager Manager { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
921 public UInt32 ID { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
922 public Delegate Target { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
923 public MethodInfo MethodSignature { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
924 public Object GetTransparentProxy() { return Target; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
925
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
926 public DelegateProxy(RemotingManager manager, UInt32 objid, MethodInfo methodinfo, Type delegateType, DynamicMethod methodBuilder) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
927 this.Manager = manager;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
928 this.ID = objid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
929 this.MethodSignature = methodinfo;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
930 Delegate mi = methodBuilder.CreateDelegate(delegateType, this);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
931 ObjectReference = new ProxyObjectReference(this);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
932 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
933 ~DelegateProxy() {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
934 Manager.ProxyReleaseObject(ObjectReference);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
935 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
936 private Object DoCall(Object[] args) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
937 return Manager.ProxyMakeCallDelegate(this, args);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
938 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
939 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
940 class FWProxy : RealProxy, IRemotingTypeInfo, IProxyBase {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
941 public RemotingManager Manager { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
942 public UInt32 ID { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
943 public ProxyObjectReference ObjectReference { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
944
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
945 public FWProxy(RemotingManager manager, UInt32 objid) : base(typeof(MarshalByRefObject)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
946 this.Manager = manager;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
947 this.ID = objid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
948 this.ObjectReference = new ProxyObjectReference(this);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
949 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
950
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
951 ~FWProxy() {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
952 Manager.ProxyReleaseObject(ObjectReference);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
953 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
954
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
955 public string TypeName { get; set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
956
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
957 public override IMessage Invoke(IMessage msg) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
958 IMethodCallMessage methodCallMessage = msg as IMethodCallMessage;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
959 if (methodCallMessage != null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
960 Object r = Manager.ProxyMakeCall(this, (MethodInfo)methodCallMessage.MethodBase, methodCallMessage.Args);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
961 return new ReturnMessage(r, null, 0, null, methodCallMessage);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
962 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
963 throw new NotImplementedException();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
964 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
965
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
966 public bool CanCastTo(Type fromType, object o) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
967 if (fromType == typeof(ISerializable)) return false;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
968 return Manager.ProxyCanCastTo(this, fromType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
969 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
970 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
971 class ProxyBase : IProxyBase {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
972 public RemotingManager Manager { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
973 public UInt32 ID { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
974 public ProxyObjectReference ObjectReference { get; private set; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
975 public Object GetTransparentProxy() { return this; }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
976
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
977 public void Init(RemotingManager manager, UInt32 objid) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
978 this.Manager = manager;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
979 this.ID = objid;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
980 this.ObjectReference = new ProxyObjectReference(this);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
981 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
982
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
983 protected Object DoCall(RuntimeMethodHandle methodh, Object[] args) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
984 MethodInfo meth = (MethodInfo)MethodInfo.GetMethodFromHandle(methodh);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
985 return Manager.ProxyMakeCall(this, meth, args);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
986 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
987
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
988 ~ProxyBase() {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
989 Manager.ProxyReleaseObject(ObjectReference);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
990 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
991 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
992
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
993 private IProxyBase CreateDelegateProxy(UInt32 objid, Type deltype) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
994 MethodInfo newMethod = deltype.GetMethod("Invoke");
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
995 ParameterInfo[] parameters = newMethod.GetParameters();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
996 Type[] mparams = ArrayUtil.Merge(new Type[1] { typeof(DelegateProxy) }, Array.ConvertAll(parameters, delegate(ParameterInfo pi) { return pi.ParameterType; }));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
997 DynamicMethod methodBuilder = new DynamicMethod(String.Empty, newMethod.ReturnType, mparams, typeof(DelegateProxy));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
998 ILGenerator ilGenerator = methodBuilder.GetILGenerator();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
999 GenerateProxyMethodCode(ilGenerator, parameters, newMethod.ReturnType, typeof(DelegateProxy), "DoCall", null);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1000 return new DelegateProxy(this, objid, newMethod, deltype, methodBuilder);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1001 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1002
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1003 private IProxyBase CreateObjectProxy(UInt32 objid, String[] typeNames) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1004 DebugLog("Create proxy for remote object {0}", objid);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1005 IProxyBase proxy;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1006 if (true) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1007 proxy = new FWProxy(this, objid);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1008 } else {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1009 Type[] types = new Type[typeNames.Length];
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1010 int j = 0;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1011 for (int i = 0; i < typeNames.Length; i++) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1012 Type t = Type.GetType(typeNames[i], false);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1013 if (t == null || !t.IsInterface) continue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1014 types[j] = t;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1015 j++;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1016 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1017 Array.Resize(ref types, j);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1018 Type proxyType = GetProxyType(types);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1019 proxy = (ProxyBase)Activator.CreateInstance(proxyType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1020 ((ProxyBase)proxy).Init(this, objid);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1021 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1022 return proxy;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1023 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1024
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1025 private static ModuleBuilder moduleBuilder = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1026 private static Dictionary<String, Type> proxyCache = null;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1027 private static Type GetProxyType(Type[] interfaceTypes) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1028 Type proxyType;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1029 String key = String.Join("&", Array.ConvertAll(interfaceTypes, delegate(Type t) { return t.Name; }));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1030 lock (typeof(RemotingManager)) if (proxyCache == null) proxyCache = new Dictionary<String, Type>();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1031 lock (proxyCache) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1032 if (!proxyCache.TryGetValue(key, out proxyType)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1033 proxyType = GenerateProxyType(key, interfaceTypes);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1034 proxyCache.Add(key, proxyType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1035 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1036 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1037 return proxyType;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1038 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1039 private static Type GenerateProxyType(String name, Type[] interfaceTypes) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1040 lock (typeof(RemotingManager)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1041 if (moduleBuilder == null) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1042 AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("UCIS.Remoting.Proxies"), AssemblyBuilderAccess.Run);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1043 moduleBuilder = assembly.DefineDynamicModule("UCIS.Remoting.Proxies", false);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1044 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1045 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1046 TypeBuilder typeBuilder = moduleBuilder.DefineType(
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1047 name.Length == 0 ? "UndefinedProxy" : name, //mono does not like types with no name!
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1048 TypeAttributes.NotPublic | TypeAttributes.Sealed,
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1049 typeof(ProxyBase),
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1050 interfaceTypes);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1051 foreach (Type interfaceType in interfaceTypes) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1052 foreach (MethodInfo method in interfaceType.GetMethods()) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1053 GenerateProxyMethod(typeBuilder, method);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1054 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1055 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1056 return typeBuilder.CreateType();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1057 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1058 private static void GenerateProxyMethod(TypeBuilder typeBuilder, MethodInfo newMethod) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1059 if (newMethod.IsGenericMethod) newMethod = newMethod.GetGenericMethodDefinition();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1060 ParameterInfo[] parameters = newMethod.GetParameters();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1061 Type[] parameterTypes = Array.ConvertAll(parameters, delegate(ParameterInfo parameter) { return parameter.ParameterType; });
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1062
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1063 MethodBuilder methodBuilder = typeBuilder.DefineMethod(
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1064 "Impl_" + newMethod.DeclaringType.Name + "_" + newMethod.Name,
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1065 MethodAttributes.Public | MethodAttributes.Virtual,
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1066 newMethod.ReturnType,
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1067 parameterTypes);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1068 typeBuilder.DefineMethodOverride(methodBuilder, newMethod);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1069
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1070 if (newMethod.IsGenericMethod) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1071 methodBuilder.DefineGenericParameters(Array.ConvertAll(newMethod.GetGenericArguments(), delegate(Type type) { return type.Name; }));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1072 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1073
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1074 ILGenerator ilGenerator = methodBuilder.GetILGenerator();
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1075 GenerateProxyMethodCode(ilGenerator, parameters, newMethod.ReturnType, typeof(ProxyBase), "DoCall", newMethod);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1076 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1077 private static void GenerateProxyMethodCode(ILGenerator ilGenerator, ParameterInfo[] parameters, Type returnType, Type baseType, String baseMethod, MethodInfo methodRef) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1078 LocalBuilder localBuilder = ilGenerator.DeclareLocal(typeof(Object[]));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1079 ilGenerator.Emit(OpCodes.Ldc_I4, parameters.Length);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1080 ilGenerator.Emit(OpCodes.Newarr, typeof(Object));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1081 ilGenerator.Emit(OpCodes.Stloc, localBuilder);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1082 for (int i = 0; i < parameters.Length; i++) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1083 if (parameters[i].ParameterType.IsByRef) continue;
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1084 ilGenerator.Emit(OpCodes.Ldloc, localBuilder);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1085 ilGenerator.Emit(OpCodes.Ldc_I4, i);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1086 ilGenerator.Emit(OpCodes.Ldarg, i + 1);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1087 if (parameters[i].ParameterType.IsValueType) ilGenerator.Emit(OpCodes.Box, parameters[i].ParameterType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1088 ilGenerator.Emit(OpCodes.Stelem_Ref);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1089 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1090 ilGenerator.Emit(OpCodes.Ldarg_0);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1091 if (methodRef != null) ilGenerator.Emit(OpCodes.Ldtoken, methodRef);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1092 ilGenerator.Emit(OpCodes.Ldloc, localBuilder);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1093 ilGenerator.Emit(OpCodes.Call, baseType.GetMethod(baseMethod, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic));
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1094 if (returnType == typeof(void)) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1095 ilGenerator.Emit(OpCodes.Pop);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1096 } else if (returnType.IsValueType) {
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1097 ilGenerator.Emit(OpCodes.Unbox_Any, returnType);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1098 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1099 ilGenerator.Emit(OpCodes.Ret);
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1100 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1101 #endregion
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1102 }
92e09198e7e7 Added Remoting code
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1103 }