/// <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); }