public CreatorMethodInvocationHandler(CreatorInterfaceInvocationHandler creatorInterfaceInvocationHandler, MethodCaller methodCaller, Type returnType, MethodInfo targetMethod) { m_CreatorInterfaceInvocationHandler = creatorInterfaceInvocationHandler; m_MethodCaller = methodCaller; m_ReturnType = returnType; m_TargetMethod = targetMethod; }
public ActorMethodInvocationHandler(IActor root, object wrapped, MethodCaller methodCaller, ProxyFactory proxyFactory, Type returnType, MethodInfo targetMethod) : base(proxyFactory, methodCaller, wrapped) { m_Root = root; m_MethodCaller = methodCaller; m_ProxyFactory = proxyFactory; m_TargetMethod = targetMethod; }
public IMethodInvocationHandler GetInvocationHandlerFor(MethodCaller methodCaller, Type returnType, MethodInfo targetMethod) { if (m_FinishedEvent.WaitOne(0)) { // m_RealInvocationHandler is already finished, forward to it return(m_RealInvocationHandler.GetInvocationHandlerFor(methodCaller, returnType, targetMethod)); } else { // It's taking a while to construct, use something that will forward to it once it's finished return(new CreatorMethodInvocationHandler(this, methodCaller, returnType, targetMethod)); } }
public IMethodInvocationHandler GetInvocationHandlerFor(MethodCaller methodCaller, Type returnType, MethodInfo targetMethod) { if (m_FinishedEvent.WaitOne(0)) { // m_RealInvocationHandler is already finished, forward to it return m_RealInvocationHandler.GetInvocationHandlerFor(methodCaller, returnType, targetMethod); } else { // It's taking a while to construct, use something that will forward to it once it's finished return new CreatorMethodInvocationHandler(this, methodCaller, returnType, targetMethod); } }
/// <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 something that takes a target and a parameters array, and will call the given method, having unpacked its arguments from the array. /// </summary> public MethodCaller CreateMethodCaller(MethodInfo methodToCall) { lock (m_Sync) { MethodCaller cachedCaller; if (m_MethodCallerCache.TryGetValue(methodToCall, out cachedCaller)) { return(cachedCaller); } } Action <object, object[]> caller = (Action <object, object[]>)CreateCallerDelegate(methodToCall, typeof(Action <object, object[]>), typeof(void)); Func <object, object[], object> returningCaller = (Func <object, object[], object>)CreateCallerDelegate(methodToCall, typeof(Func <object, object[], object>), typeof(object)); MethodCaller methodCaller = new MethodCaller(caller, returningCaller); lock (m_Sync) { m_MethodCallerCache[methodToCall] = methodCaller; } return(methodCaller); }
/// <summary> /// Creates something that, when given a delegate (compatible with the signature given here) and some parameters, will run it. /// </summary> public MethodCaller CreateDelegateCaller(Type delegateType, MethodInfo delegateSignature) { // Check the cache lock (m_Sync) { MethodCaller cachedCaller; if (m_DelegateCallerCache.TryGetValue(delegateType, out cachedCaller)) { return(cachedCaller); } } Action <object, object[]> caller = (Action <object, object[]>)CreateDelegateCallerDelegate(delegateType, delegateSignature, typeof(Action <object, object[]>), typeof(void)); Func <object, object[], object> returningCaller = (Func <object, object[], object>)CreateDelegateCallerDelegate(delegateType, delegateSignature, typeof(Func <object, object[], object>), typeof(object)); MethodCaller methodCaller = new MethodCaller(caller, returningCaller); lock (m_Sync) { m_DelegateCallerCache[delegateType] = methodCaller; } return(methodCaller); }
public IMethodInvocationHandler GetInvocationHandlerFor(MethodCaller methodCaller, Type returnType, MethodInfo targetMethod) { return new MyInvocationHandler(m_Parent); }
public IMethodInvocationHandler GetInvocationHandlerFor(MethodCaller methodCaller, Type returnType, MethodInfo targetMethod) { return(new ActorMethodInvocationHandler(m_RootForObject, m_Original, methodCaller, m_ProxyFactory, returnType, targetMethod)); }
public AudienceMethodInvocationHandler(object wrapped, MethodCaller methodCaller, ProxyFactory proxyFactory) : base(proxyFactory, methodCaller, wrapped) { }
protected MethodInvocationHandler(ProxyFactory proxyFactory, MethodCaller methodCaller, object wrapped) { m_ProxyFactory = proxyFactory; m_MethodCaller = methodCaller; m_Wrapped = wrapped; }
/// <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); }
public IMethodInvocationHandler GetInvocationHandlerFor(MethodCaller methodCaller, Type returnType, MethodInfo targetMethod) { return new AudienceMethodInvocationHandler(m_Original, methodCaller, m_ProxyFactory); }
/// <summary> /// Creates something that takes a target and a parameters array, and will call the given method, having unpacked its arguments from the array. /// </summary> public MethodCaller CreateMethodCaller(MethodInfo methodToCall) { lock (m_Sync) { MethodCaller cachedCaller; if (m_MethodCallerCache.TryGetValue(methodToCall, out cachedCaller)) { return cachedCaller; } } Action<object, object[]> caller = (Action<object, object[]>)CreateCallerDelegate(methodToCall, typeof(Action<object, object[]>), typeof(void)); Func<object, object[], object> returningCaller = (Func<object, object[], object>)CreateCallerDelegate(methodToCall, typeof(Func<object, object[], object>), typeof(object)); MethodCaller methodCaller = new MethodCaller(caller, returningCaller); lock (m_Sync) { m_MethodCallerCache[methodToCall] = methodCaller; } return methodCaller; }
/// <summary> /// Creates something that, when given a delegate (compatible with the signature given here) and some parameters, will run it. /// </summary> public MethodCaller CreateDelegateCaller(Type delegateType, MethodInfo delegateSignature) { // Check the cache lock (m_Sync) { MethodCaller cachedCaller; if (m_DelegateCallerCache.TryGetValue(delegateType, out cachedCaller)) { return cachedCaller; } } Action<object, object[]> caller = (Action<object, object[]>) CreateDelegateCallerDelegate(delegateType, delegateSignature, typeof(Action<object, object[]>), typeof(void)); Func<object, object[], object> returningCaller = (Func<object, object[], object>)CreateDelegateCallerDelegate(delegateType, delegateSignature, typeof(Func<object, object[], object>), typeof(object)); MethodCaller methodCaller = new MethodCaller(caller, returningCaller); lock (m_Sync) { m_DelegateCallerCache[delegateType] = methodCaller; } return methodCaller; }
public IMethodInvocationHandler GetInvocationHandlerFor(MethodCaller methodCaller, Type returnType, MethodInfo targetMethod) { return(new AudienceMethodInvocationHandler(m_Original, methodCaller, m_ProxyFactory)); }
public IMethodInvocationHandler GetInvocationHandlerFor(MethodCaller methodCaller, Type returnType, MethodInfo targetMethod) { return new ActorMethodInvocationHandler(m_RootForObject, m_Original, methodCaller, m_ProxyFactory, returnType, targetMethod); }