/// <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> /// Creates something that implements the given interface, and forwards all calls to the invocationHandler /// </summary> public object CreateInterfaceProxy(IInterfaceInvocationHandler invocationHandler, Type interfaceType, bool throwOnNonActorMethod) { if (!interfaceType.IsInterface) { // Only allowing interfaces for the moment, fail fast throw new InvalidOperationException("The type " + interfaceType + " is not an interface, so an NAct proxy cannot be created for it."); } if (interfaceType.IsNotPublic) { throw new InvalidOperationException("The interface " + interfaceType + " is not public, so an NAct proxy cannot be created for it."); } Type proxyType; lock (m_Sync) { m_InterfaceProxyCache.TryGetValue(interfaceType, out proxyType); } if (proxyType == null) { TypeBuilder typeBuilder = GetFreshType(); ForEveryMethodIncludingSuperInterfaces( interfaceType, delegate(MethodInfo eachMethod) { if (throwOnNonActorMethod && eachMethod.ReturnType != typeof(void) && !typeof(IActorComponent).IsAssignableFrom(eachMethod.ReturnType)) { // The method has a return type, fail fast throw new InvalidOperationException("The interface " + interfaceType + " contains the method " + eachMethod + " which has a non-void return type. Actors may only have methods with void return types."); } Type[] parameterTypes = GetParameterTypes(eachMethod); MethodBuilder methodBuilder = typeBuilder.DefineMethod(eachMethod.Name, eachMethod.Attributes & ~MethodAttributes.Abstract, eachMethod.ReturnType, parameterTypes); if (eachMethod.ReturnType == typeof(void)) { // This is an asynchronous call, use the appropriate IMethodInvocationHandler to move it to the right thread // Create a field in which to put the IMethodInvocationHandler FieldBuilder invocationHandlerField = typeBuilder.DefineField(InvocationHandlerNameForMethod(eachMethod), typeof(IMethodInvocationHandler), FieldAttributes.Private); BuildForwarderMethod(methodBuilder, parameterTypes, m_InvokeHappenedMethod, invocationHandlerField); } else { // This is a request for a subinterface - create a method that will return a proxied version of it FieldBuilder invocationHandlerField = typeBuilder.DefineField(InvocationHandlerNameForMethod(eachMethod), typeof(IMethodInvocationHandler), FieldAttributes.Private); BuildForwarderMethod(methodBuilder, parameterTypes, m_ReturningInvokeHappenedMethod, invocationHandlerField); } }); typeBuilder.AddInterfaceImplementation(interfaceType); // Finalise the type proxyType = typeBuilder.CreateType(); // Save it in the cache (this may have raced with another thread, worst that can happen is an unused extra type is created) lock (m_Sync) { m_InterfaceProxyCache[interfaceType] = proxyType; } } object proxyInstance = Activator.CreateInstance(proxyType); // Now we can write all the invocation handlers ForEveryMethodIncludingSuperInterfaces( interfaceType, delegate(MethodInfo eachMethod) { FieldInfo writeableInvocationHandlerField = proxyType.GetField(InvocationHandlerNameForMethod(eachMethod), BindingFlags.NonPublic | BindingFlags.Instance); MethodCaller methodCaller = CreateMethodCaller(eachMethod); writeableInvocationHandlerField.SetValue(proxyInstance, invocationHandler.GetInvocationHandlerFor( methodCaller, eachMethod.ReturnType, eachMethod)); }); return(proxyInstance); }
/// <summary> /// Creates something that implements the given interface, and forwards all calls to the invocationHandler /// </summary> public object CreateInterfaceProxy(IInterfaceInvocationHandler invocationHandler, Type interfaceType, bool throwOnNonActorMethod) { if (!interfaceType.IsInterface) { // Only allowing interfaces for the moment, fail fast throw new InvalidOperationException("The type " + interfaceType + " is not an interface, so an NAct proxy cannot be created for it."); } if (interfaceType.IsNotPublic) { throw new InvalidOperationException("The interface " + interfaceType + " is not public, so an NAct proxy cannot be created for it."); } Type proxyType; lock (m_Sync) { m_InterfaceProxyCache.TryGetValue(interfaceType, out proxyType); } if (proxyType == null) { TypeBuilder typeBuilder = GetFreshType(); ForEveryMethodIncludingSuperInterfaces( interfaceType, delegate(MethodInfo eachMethod) { if (throwOnNonActorMethod && eachMethod.ReturnType != typeof (void) && !typeof (IActorComponent).IsAssignableFrom(eachMethod.ReturnType)) { // The method has a return type, fail fast throw new InvalidOperationException("The interface " + interfaceType + " contains the method " + eachMethod + " which has a non-void return type. Actors may only have methods with void return types."); } Type[] parameterTypes = GetParameterTypes(eachMethod); MethodBuilder methodBuilder = typeBuilder.DefineMethod(eachMethod.Name, eachMethod.Attributes & ~MethodAttributes.Abstract, eachMethod.ReturnType, parameterTypes); if (eachMethod.ReturnType == typeof (void)) { // This is an asynchronous call, use the appropriate IMethodInvocationHandler to move it to the right thread // Create a field in which to put the IMethodInvocationHandler FieldBuilder invocationHandlerField = typeBuilder.DefineField(InvocationHandlerNameForMethod(eachMethod), typeof (IMethodInvocationHandler), FieldAttributes.Private); BuildForwarderMethod(methodBuilder, parameterTypes, m_InvokeHappenedMethod, invocationHandlerField); } else { // This is a request for a subinterface - create a method that will return a proxied version of it FieldBuilder invocationHandlerField = typeBuilder.DefineField(InvocationHandlerNameForMethod(eachMethod), typeof (IMethodInvocationHandler), FieldAttributes.Private); BuildForwarderMethod(methodBuilder, parameterTypes, m_ReturningInvokeHappenedMethod, invocationHandlerField); } }); typeBuilder.AddInterfaceImplementation(interfaceType); // Finalise the type proxyType = typeBuilder.CreateType(); // Save it in the cache (this may have raced with another thread, worst that can happen is an unused extra type is created) lock (m_Sync) { m_InterfaceProxyCache[interfaceType] = proxyType; } } object proxyInstance = Activator.CreateInstance(proxyType); // Now we can write all the invocation handlers ForEveryMethodIncludingSuperInterfaces( interfaceType, delegate(MethodInfo eachMethod) { FieldInfo writeableInvocationHandlerField = proxyType.GetField(InvocationHandlerNameForMethod(eachMethod), BindingFlags.NonPublic | BindingFlags.Instance); MethodCaller methodCaller = CreateMethodCaller(eachMethod); writeableInvocationHandlerField.SetValue(proxyInstance, invocationHandler.GetInvocationHandlerFor( methodCaller, eachMethod.ReturnType, eachMethod)); }); return proxyInstance; }