diff --git a/Hazelcast.Net/Hazelcast.Client.Spi/ProxyManager.cs b/Hazelcast.Net/Hazelcast.Client.Spi/ProxyManager.cs index 2cfb0c691f..b6e6215b60 100644 --- a/Hazelcast.Net/Hazelcast.Client.Spi/ProxyManager.cs +++ b/Hazelcast.Net/Hazelcast.Client.Spi/ProxyManager.cs @@ -108,25 +108,58 @@ public ICollection GetDistributedObjects() return new ReadOnlyCollection(_proxies.Values.ToList()); } - public ClientProxy GetOrCreateProxy(string service, string id) + public ClientProxy GetOrCreateProxy(string service, string id) where T : IDistributedObject { var ns = new ObjectNamespace(service, id); ClientProxy proxy; _proxies.TryGetValue(ns, out proxy); + var requestedInterface = typeof (T); if (proxy != null) { - return proxy; + // only return the existing proxy, if the requested type args match + var proxyInterface = proxy.GetType().GetInterface(requestedInterface.Name); + var proxyArgs = proxyInterface.GetGenericArguments(); + var requestedArgs = requestedInterface.GetGenericArguments(); + if (proxyArgs.SequenceEqual(requestedArgs)) + { + // the proxy we found matches what we were looking for + return proxy; + } + + // create a new proxy, which matches the interface requested + proxy = makeProxy(service, id, requestedInterface); } - ClientProxyFactory factory; + else + { + // create a new proxy, which needs initialization on server. + proxy = makeProxy(service, id, requestedInterface); + InitializeWithRetry(proxy); + } + + proxy.SetContext(new ClientContext(_client.GetSerializationService(), + _client.GetClientClusterService(), + _client.GetClientPartitionService(), _client.GetInvocationService(), _client.GetClientExecutionService(), + _client.GetListenerService(), + this, _client.GetClientConfig())); + proxy.PostInit(); + + _proxies.AddOrUpdate(ns, n => proxy, (n, oldProxy) => { + Logger.Warning("Replacing old proxy for " + oldProxy.GetName() + " of type " + oldProxy.GetType() + " with " + proxy.GetType()); + return proxy; + }); + return proxy; + } + private ClientProxy makeProxy(string service, string id, Type requestedInterface) + { + ClientProxyFactory factory; _proxyFactories.TryGetValue(service, out factory); if (factory == null) { throw new ArgumentException("No factory registered for service: " + service); } - var clientProxy = factory(typeof (T), id); - InitializeWithRetry(clientProxy); - return _proxies.GetOrAdd(ns, clientProxy); + var clientProxy = factory(requestedInterface, id); + return clientProxy; } public ClientProxy GetProxy(string service, string id) @@ -225,9 +258,8 @@ internal static ClientProxy ProxyFactory(Type proxyType, Type interfaceType, str { if (proxyType.ContainsGenericParameters) { - var genericTypeArguments = interfaceType.GetGenericArguments(); - var mgType = proxyType.MakeGenericType(genericTypeArguments); - return Activator.CreateInstance(mgType, name, id) as ClientProxy; + var typeWithParams = GetTypeWithParameters(proxyType, interfaceType); + return Activator.CreateInstance(typeWithParams, name, id) as ClientProxy; } return Activator.CreateInstance(proxyType, name, id) as ClientProxy; } @@ -253,7 +285,22 @@ private Address FindNextAddressToCreateARequest() return liteMember != null ? liteMember.GetAddress() : null; } - private void Initialize(ClientProxy clientProxy) + private static Type GetTypeWithParameters(Type proxyType, Type interfaceType) + { + var genericTypeArguments = interfaceType.GetGenericArguments(); + if (genericTypeArguments.Length == proxyType.GetGenericArguments().Length) + { + return proxyType.MakeGenericType(genericTypeArguments); + } + var types = new Type[proxyType.GetGenericArguments().Length]; + for (var i = 0; i < types.Length; i++) + { + types[i] = typeof (object); + } + return proxyType.MakeGenericType(types); + } + + private void InitializeOnServer(ClientProxy clientProxy) { var initializationTarget = FindNextAddressToCreateARequest(); var invocationTarget = initializationTarget; @@ -278,12 +325,6 @@ private void Initialize(ClientProxy clientProxy) { throw ExceptionUtil.Rethrow(e); } - clientProxy.SetContext(new ClientContext(_client.GetSerializationService(), - _client.GetClientClusterService(), - _client.GetClientPartitionService(), _client.GetInvocationService(), _client.GetClientExecutionService(), - _client.GetListenerService(), - this, _client.GetClientConfig())); - clientProxy.PostInit(); } private void InitializeWithRetry(ClientProxy clientProxy) @@ -294,7 +335,7 @@ private void InitializeWithRetry(ClientProxy clientProxy) { try { - Initialize(clientProxy); + InitializeOnServer(clientProxy); return; } catch (Exception e) diff --git a/Hazelcast.Test/Hazelcast.Client.Test/ClientDistributedObjectTest.cs b/Hazelcast.Test/Hazelcast.Client.Test/ClientDistributedObjectTest.cs index 7bf647bd25..ffd036b6be 100644 --- a/Hazelcast.Test/Hazelcast.Client.Test/ClientDistributedObjectTest.cs +++ b/Hazelcast.Test/Hazelcast.Client.Test/ClientDistributedObjectTest.cs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Threading; using Hazelcast.Core; using NUnit.Framework; @@ -40,19 +41,37 @@ public void TestDistributedObjectListener() [Test] public void TestGetDistributedObjects() { - var queue = Client.GetMap(TestSupport.RandomString()); + var map = Client.GetMap(TestSupport.RandomString()); var topic = Client.GetTopic(TestSupport.RandomString()); var semaphore = Client.GetSemaphore(TestSupport.RandomString()); + Assert.AreEqual(3, Client.GetDistributedObjects().Count); - queue.Destroy(); + map.Destroy(); topic.Destroy(); semaphore.Destroy(); Assert.AreEqual(0, Client.GetDistributedObjects().Count); } + [Test] + public void TestGetDistributedObjectsFromAnotherClient() + { + String mapName = TestSupport.RandomString(); + var map = Client.GetMap(mapName); + Client.GetTopic(TestSupport.RandomString()); + Client.GetSemaphore(TestSupport.RandomString()); + + map.Put(1, 1); + var client2 = CreateClient(); + + Assert.AreEqual(3, client2.GetDistributedObjects().Count); + + var map2 = client2.GetMap(mapName); + Assert.AreEqual(1, map2.Get(1)); + } + private class DistributedObjectListener : IDistributedObjectListener { private readonly CountdownEvent _createdLatch;