public override object ReturningInvokeHappened(object[] parameterValues) { // This is only allowed if the returning method gets a IActorCompoment // TODO Use a CIIH or something to run the getter method asynchronously in the root actor's thread //CreatorInterfaceInvocationHandler creatorInvocationHandler = new CreatorInterfaceInvocationHandler( // () => (IActorComponent)m_MethodBeingProxied.Invoke(m_Wrapped, parameterValues), m_Root, m_ProxyFactory); object subInterfaceObject = base.ReturningInvokeHappened(parameterValues); // 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 subInterfaceObject.GetType().GetInterfaces()) { if (typeof(IActorComponent).IsAssignableFrom(eachInterface)) { interfaceType = eachInterface; break; } } ActorInterfaceInvocationHandler invocationHandler = new ActorInterfaceInvocationHandler(subInterfaceObject, m_Root, m_ProxyFactory); return(m_ProxyFactory.CreateInterfaceProxy(invocationHandler, interfaceType, true)); }
/// <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); }