/// <summary> /// Creates the proxy. /// </summary> /// <returns>Contract</returns> public TContract CreateProxy() { ConstructorInfo c = mRealProxyType.GetConstructor(new Type[] { typeof(Channel), typeof(String) }); ProxyBase proxy = (ProxyBase)c.Invoke(new object[] { mChannel, mChannel.Connect(mRemoteEndPoint) }); WellKnownObjectModeEnum mode = WellKnownObjectModeEnum.PerSession; if (ContractValidator.GetWellKnownObjectMode(mContractInterface, out mode) && mode == WellKnownObjectModeEnum.PerSession) { ServiceBase.RegisterProxy(mChannel, mContractInterface, proxy.GetType(), proxy.SessionId, proxy.ProxyId, proxy); } return((TContract)(IRemoteContract)proxy); }
/// <summary> /// Channels the receive message event handler. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="Forge.Net.Remoting.Channels.ReceiveMessageEventArgs"/> instance containing the event data.</param> protected override void ChannelReceiveMessageEventHandler(object sender, ReceiveMessageEventArgs e) { if (LOGGER.IsDebugEnabled) { LOGGER.Debug(string.Format("Executing service method. SessionId: '{0}', {1}", e.SessionId, e.Message.ToString())); } Channel channel = (Channel)sender; String sessionId = e.SessionId; IMessage message = e.Message; // Request és response message type jöhet // Request mode // Response mode // Datagram mode - nincs válasz if (message.MessageType == MessageTypeEnum.Acknowledge || message.MessageType == MessageTypeEnum.Response) { // HIBA: nem megfelelő üzenet típus (implementációs hiba?) String errorMsg = String.Format("Invalid message type received: {0}. This may be an implementation error in the client proxy.", message.MessageType); if (LOGGER.IsErrorEnabled) { LOGGER.Error(errorMsg); } } else { RequestMessage rm = (RequestMessage)message; if (MessageInvokeModeEnum.RequestCallback.Equals(rm.MessageInvokeMode)) { return; } String contractName = rm.ContractName; Type contractType = null; try { contractType = TypeHelper.GetTypeFromString(contractName); } catch (Exception ex) { // HIBA: ez a típus nem szerepel a ClassPath-ban try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to resolve this type of contract '{0}'. Type has not found.", rm.ContractName), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } ContractServiceSideDescriptor descriptor = null; lock (mContractDescriptors) { if (mContractDescriptors.ContainsKey(contractType)) { descriptor = mContractDescriptors[contractType]; } else { // HIBA: ez a contract nincs nyilvántartva try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("This type of contract '{0}' has not been registered.", contractType.FullName)), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } } Type implType = null; lock (descriptor) { if (descriptor.ImplementationPerChannel.ContainsKey(channel.ChannelId)) { implType = descriptor.ImplementationPerChannel[channel.ChannelId]; } else if (descriptor.DefaultImplementationType != null) { implType = descriptor.DefaultImplementationType; } else { // HIBA: a contract a megadott channel-hez nem definiált implementációs típust try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to find implementation for this type of contract '{0}' and channel id: '{1}'.", contractType.FullName, channel.ChannelId)), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } } Object instance = null; WellKnownObjectModeEnum objectMode = WellKnownObjectModeEnum.PerSession; ContractValidator.GetWellKnownObjectMode(contractType, out objectMode); if (objectMode == WellKnownObjectModeEnum.PerSession) { // constructor keresése a Channel és String paraméterlistával, ha még ehhez a session-hez nem létezik instance long proxyId = -1; try { proxyId = (long)rm.Context[ProxyBase.PROXY_ID]; } catch (Exception ex) { // HIBA: hiányzó vagy rossz formátumú ProxyId try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException("Unable to parse PROXY_ID from call context.", ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } lock (mContractAndInstancePerSessionAndChannel) { foreach (ContractAndInstanceStruct s in mContractAndInstancePerSessionAndChannel) { if (s.Channel.Equals(channel) && s.ContractType.Equals(contractType) && s.SessionId.Equals(sessionId) && s.ImplType.Equals(implType) && s.ProxyId == proxyId) { instance = s.Instance; break; } } if (instance == null) { // még nem létezik a proxy példány, létre kell hozni try { ConstructorInfo c = implType.GetConstructor(new Type[] { typeof(Channel), typeof(String) }); instance = c.Invoke(new object[] { channel, sessionId }); RegisterProxy(channel, contractType, implType, sessionId, proxyId, (ProxyBase)instance); } catch (Exception ex) { // HIBA: sikertelen az instance létrehozása try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to instantiate type '{0}'. Public constructor is not accessible/found with parameter types: '{1}' and '{2}'.", implType.FullName, typeof(Channel).FullName, typeof(String).FullName), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } } } } else if (objectMode == WellKnownObjectModeEnum.Singleton) { // üres constructor kell, ha még nem létezik az instance lock (mSingletonContainer) { if (mSingletonContainer.ContainsKey(implType)) { instance = mSingletonContainer[implType]; } else { try { // még nem volt létrehozva instance = implType.GetConstructor(new Type[] { }).Invoke(null); mSingletonContainer.Add(implType, instance); } catch (Exception ex) { // HIBA: sikertelen az instance létrehozása try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to instantiate type '{0}'. Public empty constructor is not accessible/found.", implType.FullName), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } } } } else { // üres constructor kell, példányosítás mindig megtörténik try { // még nem volt létrehozva instance = implType.GetConstructor(new Type[] { }).Invoke(null); } catch (Exception ex) { // HIBA: sikertelen az instance létrehozása try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to instantiate type '{0}'. Public empty constructor is not accessible/found.", implType.FullName), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } } // meg van az instance, lehet reflection-nel hívni a metódusára Type[] methodParamTypes = null; Object[] paramValues = null; if (rm.MethodParameters != null) { methodParamTypes = new Type[rm.MethodParameters.Length]; paramValues = new Object[rm.MethodParameters.Length]; for (int i = 0; i < rm.MethodParameters.Length; i++) { try { methodParamTypes[i] = TypeHelper.GetTypeFromString(rm.MethodParameters[i].ClassName); } catch (Exception ex) { // HIBA: a paraméter egy típusa nem szerepel a Domainben, így nem feloldható, ismeretlen try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to resolve parameter type '{0}'. Type has not found.", rm.MethodParameters[i].ClassName), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } paramValues[i] = rm.MethodParameters[i].Value; } } MethodInfo m = null; try { m = FindMethod(implType, rm.MethodName, methodParamTypes); } catch (Exception ex) { // HIBA: a metódus név és paraméterlista alapján nem található try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to find method '{0}' with parameter list: '{1}'.", rm.MethodName, methodParamTypes), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } long returnTimeout = OperationContractAttribute.DEFAULT_METHOD_TIMEOUT; if (rm.MessageType == MessageTypeEnum.Request) { MethodParameter[] mps = null; if (m.GetParameters().Length > 0) { mps = new MethodParameter[m.GetParameters().Length]; for (int i = 0; i < m.GetParameters().Length; i++) { ParameterInfo pi = m.GetParameters()[i]; mps[i] = new MethodParameter(i, string.Format("{0}, {1}", pi.ParameterType.FullName, new AssemblyName(pi.ParameterType.Assembly.FullName).Name), null); } } returnTimeout = ServiceBase.GetTimeoutByMethod(contractType, m.Name, mps, MethodTimeoutEnum.ReturnTimeout); lock (mCallContextForReply) { mCallContextForReply.Add(Thread.CurrentThread, new CallContextForReply(channel, sessionId, rm, m.ReturnType, returnTimeout)); } } // visszatérési értéket fogadni Exception methodException = null; Object result = null; try { result = m.Invoke(instance, paramValues); } catch (Exception ex) { if (LOGGER.IsDebugEnabled) { LOGGER.Debug(string.Format("Service method threw an exception. SessionId: '{0}', {1}", e.SessionId, e.Message.ToString()), ex); } methodException = ex; } // válaszüzenet küldése bool needToSendResponse = false; Type returnType = typeof(void); if (rm.MessageType == MessageTypeEnum.Request) { lock (mCallContextForReply) { if (mCallContextForReply.ContainsKey(Thread.CurrentThread)) { needToSendResponse = true; returnType = mCallContextForReply[Thread.CurrentThread].ReturnType; } } } if (needToSendResponse) { try { SendResponse(channel, sessionId, rm, returnType, result, methodException, returnTimeout); } catch (Exception ex) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, ex.Message)); } } finally { lock (mCallContextForReply) { mCallContextForReply.Remove(Thread.CurrentThread); } } } // saját tulajdonú instance, ami implementálja az IDisposable interface-t és SingleCall, akkor ráhívok a Dispose() metódusra if (objectMode == WellKnownObjectModeEnum.SingleCall && instance is IDisposable) { ((IDisposable)instance).Dispose(); } } }
/// <summary> /// Initializes a new instance of the <see cref="ProxyGenerator<TContract>"/> class. /// </summary> public ProxyGenerator() { ContractValidator.ValidateContractIntegrity(ContractType); ContractValidator.GetWellKnownObjectMode(ContractType, out mWellKnownObjectMode); }
/// <summary> /// Channels the receive message event handler. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="Forge.Net.Remoting.Channels.ReceiveMessageEventArgs"/> instance containing the event data.</param> protected override void ChannelReceiveMessageEventHandler(object sender, ReceiveMessageEventArgs e) { Channel channel = (Channel)sender; IMessage message = e.Message; String sessionId = e.SessionId; if (message.MessageType == MessageTypeEnum.Acknowledge || message.MessageType == MessageTypeEnum.Response) { // HIBA: nem megfelelő üzenet típus (implementációs hiba?) String errorMsg = String.Format("Invalid message type received: {0}. This may be an implementation error in the client proxy.", message.MessageType.ToString()); if (LOGGER.IsErrorEnabled) { LOGGER.Error(errorMsg); } } else { RequestMessage rm = (RequestMessage)message; if (MessageInvokeModeEnum.RequestService.Equals(rm.MessageInvokeMode)) { return; } String contractName = rm.ContractName; Type contractType = null; try { contractType = TypeHelper.GetTypeFromString(contractName); } catch (Exception ex) { // HIBA: ez a típus nem szerepel a ClassPath-ban try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to resolve this type of contract '{0}'. Type has not found.", rm.ContractName), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } { WellKnownObjectModeEnum mode = WellKnownObjectModeEnum.PerSession; if (ContractValidator.GetWellKnownObjectMode(contractType, out mode) && mode != WellKnownObjectModeEnum.PerSession) { // HIBA: nem PerSession a contract, amit meghívnak try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Contract {0} must be configured to {1}.", typeof(WellKnownObjectModeEnum).Name, WellKnownObjectModeEnum.PerSession.ToString())), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } } lock (mContractDescriptors) { if (!mContractDescriptors.ContainsKey(contractType)) { // HIBA: ez a contract nincs nyilvántartva try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("This type of contract '{0}' has not been registered.", contractType.Name)), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } } long proxyId = -1; try { proxyId = (long)rm.Context[ProxyBase.PROXY_ID]; } catch (Exception ex) { // HIBA: hiányzó vagy rossz formátumú ProxyId try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException("Unable to parse PROXY_ID from call context.", ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } ProxyBase proxy = null; lock (mContractAndInstancePerSessionAndChannel) { foreach (ContractAndInstanceStruct s in mContractAndInstancePerSessionAndChannel) { if (s.Channel.Equals(channel) && s.ContractType.Equals(contractType) && s.SessionId.Equals(sessionId) && s.ProxyId == proxyId) { proxy = s.Instance; break; } } if (proxy == null) { // HIBA: nem létezik a hivatkozott proxy példány try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to find proxy on client side with ID: {0}", proxyId)), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } } // meg van az instance, lehet reflection-nel hívni a metódusára Type[] methodParamTypes = null; Object[] paramValues = null; if (rm.MethodParameters != null) { methodParamTypes = new Type[rm.MethodParameters.Length]; paramValues = new Object[rm.MethodParameters.Length]; for (int i = 0; i < rm.MethodParameters.Length; i++) { try { methodParamTypes[i] = TypeHelper.GetTypeFromString(rm.MethodParameters[i].ClassName); } catch (Exception ex) { // HIBA: a paraméter egy típusa nem szerepel a CLASSPATH-ban, így nem feloldható, ismeretlen try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to resolve parameter type '{0}'. Type has not found.", rm.MethodParameters[i].ClassName), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } paramValues[i] = rm.MethodParameters[i].Value; } } MethodInfo m = null; try { m = FindMethod(proxy.GetType(), rm.MethodName, methodParamTypes); } catch (Exception ex) { // HIBA: a metódus név és paraméterlista alapján nem található try { SendResponse(channel, sessionId, rm, typeof(void), null, new MethodInvocationException(String.Format("Unable to find method '{0}' with parameter list: '{1}'.", rm.MethodName, methodParamTypes), ex), channel.DefaultErrorResponseTimeout); } catch (Exception innerEx) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, innerEx.Message)); } } return; } long returnTimeout = OperationContractAttribute.DEFAULT_METHOD_TIMEOUT; if (rm.MessageType == MessageTypeEnum.Request) { MethodParameter[] mps = null; if (m.GetParameters().Length > 0) { mps = new MethodParameter[m.GetParameters().Length]; for (int i = 0; i < m.GetParameters().Length; i++) { ParameterInfo pi = m.GetParameters()[i]; mps[i] = new MethodParameter(i, string.Format("{0}, {1}", pi.ParameterType.FullName, new AssemblyName(pi.ParameterType.Assembly.FullName).Name), null); } } returnTimeout = ServiceBase.GetTimeoutByMethod(contractType, m.Name, mps, MethodTimeoutEnum.ReturnTimeout); lock (mCallContextForReply) { mCallContextForReply.Add(Thread.CurrentThread, new CallContextForReply(channel, sessionId, rm, m.ReturnType, returnTimeout)); } } // visszatérési értéket fogadni Exception methodException = null; Object result = null; try { result = m.Invoke(proxy, paramValues); } catch (Exception ex) { methodException = ex; } // válaszüzenet küldése bool needToSendResponse = false; Type returnType = typeof(void); if (rm.MessageType == MessageTypeEnum.Request) { lock (mCallContextForReply) { if (mCallContextForReply.ContainsKey(Thread.CurrentThread)) { needToSendResponse = true; returnType = mCallContextForReply[Thread.CurrentThread].ReturnType; } } } if (needToSendResponse) { try { SendResponse(channel, sessionId, rm, returnType, result, methodException, returnTimeout); } catch (Exception ex) { // válaszüzenet küldése sikertelen if (LOGGER.IsErrorEnabled) { LOGGER.Error(String.Format(AUTO_SEND_REPLY_ERROR_MSG, ex.Message)); } } finally { lock (mCallContextForReply) { mCallContextForReply.Remove(Thread.CurrentThread); } } } } }