/// <summary>
        /// Checks an object for being a callback, and proxies it to move to the right thread if it is
        /// </summary>
        /// <param name="original">The original object that might be a callback</param>
        /// <returns>The object that should now be the parameter, either just original, or a proxy for it if it was a callback</returns>
        private object ConvertParameter(object original)
        {
            // See if this parameter is, or is in, an actor
            IActor rootForObject = RootForObject(original);

            if (rootForObject != null)
            {
                Delegate originalAsDelegate = original as Delegate;
                if (originalAsDelegate != null)
                {
                    // Special case for delegates: make a new delegate that calls the existing one in the right thread
                    Type returnType = originalAsDelegate.Method.ReturnType;
                    if (returnType != typeof(void))
                    {
                        // The method has a return type, fail fast
                        throw new InvalidOperationException("The delegate " + originalAsDelegate.GetType() +
                                                            " has a non-void return type. Actors may only be given callbacks with void return types.");
                    }
                    MethodCaller delegateMethodCaller = m_ProxyFactory.CreateDelegateCaller(originalAsDelegate.GetType(), originalAsDelegate.Method);
                    ActorMethodInvocationHandler methodInvocationHandler = new ActorMethodInvocationHandler(rootForObject, originalAsDelegate, delegateMethodCaller, m_ProxyFactory, returnType, originalAsDelegate.Method);
                    return(m_ProxyFactory.CreateDelegateProxy(methodInvocationHandler, originalAsDelegate.Method, original.GetType()));
                }
                else
                {
                    // Yep, this object needs to be wrapped to move back to its actor's logical thread when it's used
                    ActorInterfaceInvocationHandler callbackInterceptor = new ActorInterfaceInvocationHandler(original, rootForObject, m_ProxyFactory);

                    // Find the object's interface which implements IActor (it might have others, but this is the important one)
                    Type interfaceType = null;
                    foreach (Type eachInterface in original.GetType().GetInterfaces())
                    {
                        if (typeof(IActor).IsAssignableFrom(eachInterface) && !eachInterface.Equals(typeof(IActor)))
                        {
                            interfaceType = eachInterface;
                            break;
                        }
                    }

                    if (interfaceType == null)
                    {
                        throw new ApplicationException("NAct encountered an internal inconsistency and will eat your cake.");
                    }

                    return(m_ProxyFactory.CreateInterfaceProxy(callbackInterceptor, interfaceType, true));
                }
            }

            return(original);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Checks an object for being a callback, and proxies it to move to the right thread if it is
        /// </summary>
        /// <param name="original">The original object that might be a callback</param>
        /// <returns>The object that should now be the parameter, either just original, or a proxy for it if it was a callback</returns>
        private object ConvertParameter(object original)
        {
            // See if this parameter is, or is in, an actor
            IActor rootForObject = RootForObject(original);

            if (rootForObject != null)
            {
                Delegate originalAsDelegate = original as Delegate;
                if (originalAsDelegate != null)
                {
                    // Special case for delegates: make a new delegate that calls the existing one in the right thread
                    Type returnType = originalAsDelegate.Method.ReturnType;
                    if (returnType != typeof(void))
                    {
                        // The method has a return type, fail fast
                        throw new InvalidOperationException("The delegate " + originalAsDelegate.GetType() +
                                                            " has a non-void return type. Actors may only be given callbacks with void return types.");
                    }
                    MethodCaller delegateMethodCaller = m_ProxyFactory.CreateDelegateCaller(originalAsDelegate.GetType(), originalAsDelegate.Method);
                    ActorMethodInvocationHandler methodInvocationHandler = new ActorMethodInvocationHandler(rootForObject, originalAsDelegate, delegateMethodCaller, m_ProxyFactory, returnType, originalAsDelegate.Method);
                    return m_ProxyFactory.CreateDelegateProxy(methodInvocationHandler, originalAsDelegate.Method, original.GetType());
                }
                else
                {
                    // Yep, this object needs to be wrapped to move back to its actor's logical thread when it's used
                    ActorInterfaceInvocationHandler callbackInterceptor = new ActorInterfaceInvocationHandler(original, rootForObject, m_ProxyFactory);

                    // Find the object's interface which implements IActor (it might have others, but this is the important one)
                    Type interfaceType = null;
                    foreach (Type eachInterface in original.GetType().GetInterfaces())
                    {
                        if (typeof(IActor).IsAssignableFrom(eachInterface) && !eachInterface.Equals(typeof(IActor)))
                        {
                            interfaceType = eachInterface;
                            break;
                        }
                    }

                    if (interfaceType == null)
                    {
                        throw new ApplicationException("NAct encountered an internal inconsistency and will eat your cake.");
                    }

                    return m_ProxyFactory.CreateInterfaceProxy(callbackInterceptor, interfaceType, true);
                }
            }

            return original;
        }