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); }
/// <summary> /// Creates a proxy for an actor component object and places it in an existing actor /// </summary> internal CreatorInterfaceInvocationHandler(ObjectCreator <IActorComponent> creator, IActor rootObject, ProxyFactory proxyFactory) { // We need to lock on the root when using an existing actor ThreadPool.QueueUserWorkItem( delegate { Hooking.ActorCallWrapper(() => { IActorComponent newObject = creator(); ActorInterfaceInvocationHandler temp = new ActorInterfaceInvocationHandler(newObject, rootObject, proxyFactory); m_RealInvocationHandler = temp; m_FinishedEvent.Set(); }); }); }
/// <summary> /// Creates an interceptor for an object that doesn't exist yet. /// /// This will trigger its asynchronous construction. /// </summary> public CreatorInterfaceInvocationHandler(ObjectCreator <IActor> creator, ProxyFactory proxyFactory) { ThreadPool.QueueUserWorkItem( delegate { Hooking.ActorCallWrapper( () => { IActor newObject = creator(); ActorInterfaceInvocationHandler temp = new ActorInterfaceInvocationHandler(newObject, newObject, proxyFactory); m_RealInvocationHandler = temp; m_FinishedEvent.Set(); }); }); }
/// <summary> /// Creates a proxy for an actor component object and places it in an existing actor /// </summary> internal CreatorInterfaceInvocationHandler(ObjectCreator<IActorComponent> creator, IActor rootObject, ProxyFactory proxyFactory) { // We need to lock on the root when using an existing actor ThreadPool.QueueUserWorkItem( delegate { Hooking.ActorCallWrapper(() => { IActorComponent newObject = creator(); ActorInterfaceInvocationHandler temp = new ActorInterfaceInvocationHandler(newObject, rootObject, proxyFactory); m_RealInvocationHandler = temp; m_FinishedEvent.Set(); }); }); }
/// <summary> /// Creates an interceptor for an object that doesn't exist yet. /// /// This will trigger its asynchronous construction. /// </summary> public CreatorInterfaceInvocationHandler(ObjectCreator<IActor> creator, ProxyFactory proxyFactory) { ThreadPool.QueueUserWorkItem( delegate { Hooking.ActorCallWrapper( () => { IActor newObject = creator(); ActorInterfaceInvocationHandler temp = new ActorInterfaceInvocationHandler(newObject, newObject, proxyFactory); m_RealInvocationHandler = temp; m_FinishedEvent.Set(); }); }); }
/// <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; }
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); }