/// <summary> /// Will register a subscriber. Event will be recognized by "eventId" and will be attached to /// obj /// </summary> /// <param name="eventId"></param> /// <param name="obj"></param> /// <param name="handler"></param> public void Subscribe(string eventId, IStateObject obj, Delegate handler, out string eventSubscriptionId, bool isDynamic = false) { var result = String.Empty; if (handler != null) { //get/created subscribed promises info eventId = eventId.ToUpper(); var handlerSubscriptionId = UniqueIDGenerator.GetEventRelativeUniqueID(obj, eventId); LazyBehaviours.AddDependent(obj, UniqueIDGenerator.EVENTPrefix + eventId); var promisesInfo = PromisesInfo.CreateInstance(handlerSubscriptionId); ////subscribe handler var eventMethodName = handler.Method.Name.ToUpper() + eventId; eventSubscriptionId = UniqueIDGenerator.GetEventRelativeUniqueID(obj, eventMethodName); LazyBehaviours.AddDependent(obj, UniqueIDGenerator.EVENTPrefix + eventMethodName); promisesInfo.Add(eventMethodName); if (isDynamic) { EventPromiseInfoForClient.CreateEventInstance(_stateManager, handler, obj, eventSubscriptionId, actionID: eventId); } else { EventPromiseInfo.CreateEventInstance(_stateManager, handler, obj, eventSubscriptionId); } #if DEBUG Debug.Assert(_stateManager.GetObject(eventSubscriptionId) != null, "Event Subscription Failed", "Event for {0} on Object {1} failed", eventId, obj.UniqueID); #endif result = eventSubscriptionId; } eventSubscriptionId = result; }
private Delegate PublishInternal(EventPromiseInfo eventHandlerInfo, string eventId, IStateObject source, bool doNotCall, params object[] args) { var delegateType = TypeCacheUtils.GetType(eventHandlerInfo.DelegateType); Delegate eventDelegate = PromiseUtils.FromContinuationInfo(delegateType, eventHandlerInfo, source) as Delegate; if (eventDelegate == null) { TraceUtil.TraceError("EventAggregator::PublishInternal Error publishing event. Continuation could not be restored"); return(null); } if (doNotCall) { return(eventDelegate); } TraceUtil.TraceInformation("Publishing event " + eventId); if (eventDelegate != null) { try { eventDelegate.Method.Invoke(eventDelegate.Target, args); } catch (TargetInvocationException tiex) { var baseException = tiex.GetBaseException(); PreserveStackTrace(baseException); throw baseException; } } return(eventDelegate); }
/// <summary> /// Creates a PromiseInfo related to Events to be subscribed /// </summary> public static EventPromiseInfo CreateEventInstance(StateManager stateManager, Delegate code, IStateObject parent = null, string promiseUniqueId = null, PromiseState state = PromiseState.Resolved, string actionID = "") { var instance = new EventPromiseInfo { State = state }; BuildContinuationInfo(stateManager, instance, code, parent, promiseUniqueId, actionID: actionID); return(instance); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { EventPromiseInfo target = null; if (reader.TokenType == JsonToken.Null) { return(null); } target = existingValue as EventPromiseInfo; if (reader.TokenType == JsonToken.StartArray) { target.StateObjectUniqueId = reader.ReadAsString(); string datastring = reader.ReadAsString(); int baseLen = TypeCacheUtils.PADDEDCONTRACTEDTYPENAME; int idx = 0; target.DeclaringType = datastring.Substring(idx, baseLen); idx += baseLen; target.DelegateType = datastring.Substring(idx, baseLen); idx += baseLen; target.TargetType = datastring.Substring(idx, baseLen); idx += baseLen; if (target.TargetType == IntegerExtensions.getNullByBase(baseLen)) { target.TargetType = null; } string args = datastring.Substring(idx, datastring.Length - idx); StringBuilder builder = new StringBuilder(); if (args.Length > 0) { int posidx = 0; //add token separator(added in BuildContinuationInfo), continue use in original code do { builder.Append(args.Substring(posidx, baseLen)); builder.Append("|"); posidx += baseLen; } while (posidx < args.Length); } target.MethodArgs = builder.ToString(); target.MethodName = reader.ReadAsString(); target.State = (PromiseState)reader.ReadAsInt32().Value; target.ParentId = reader.ReadAsString(); target.ActionID = reader.ReadAsString(); } return(target); }
internal static EventPromiseInfo BuildContinuationInfo(StateManager stateManager, EventPromiseInfo promise, Delegate code, IStateObject parent = null, string promiseUniqueId = null, string actionID = "") { var instance = code.Target; Type codePromiseType = instance != null?instance.GetType() : null; string internalFieldsState = null; //This variable holds the reference //to the IStateObject that is closest to the promise. //For example if we are referring to a method on a Form. The closest state object is a //ViewModel. If the object is a DisplayClass, then we try to determine //which was the closest IModel or IUserControl where this DisplayClass was used IStateObject objectContainingMethod = null; if (codePromiseType != null) { //For special classes it's required to register a surrogate to save the application state. if (TypeCacheUtils.IsSpecialClass(codePromiseType)) { PromiseUtils.RegisterSurrogateForDisplayClass(codePromiseType, code.Target); objectContainingMethod = stateManager.surrogateManager.GetSurrogateFor(code.Target, generateIfNotFound: true); } else { var stateObject = instance as IStateObject; if (stateObject != null) { objectContainingMethod = stateObject; } else { var logicView = instance as ILogicView <IViewModel>; if (logicView != null) { objectContainingMethod = logicView.ViewModel; } } } } string methodArgs = null; var parameters = code.Method.GetParameters(); if (parameters.Length > 0) { StringBuilder builder = new StringBuilder(); foreach (var parameter in parameters) { builder.Append(parameter.ParameterType.AssemblyQualifiedNameCache()); builder.Append("|"); } methodArgs = builder.ToString(); } promise.DeclaringType = code.Method.DeclaringType.AssemblyQualifiedNameCache(); //promise.SetObjectContainingMethod(objectContainingMethod); promise.TargetType = code.Target != null?code.Target.GetType().AssemblyQualifiedNameCache() : null; promise.MethodName = code.Method.Name; promise.ActionID = actionID; promise.ParentId = parent != null ? parent.UniqueID : promise.ModalUniqueId = null; promise.MethodArgs = methodArgs; promise.UniqueID = promiseUniqueId ?? (parent == null ? stateManager.UniqueIDGenerator.GetPromiseUniqueID() : stateManager.UniqueIDGenerator.GetRelativeUniqueID(parent)); promise.ContinuationFields = internalFieldsState; promise.DelegateType = TypeCacheUtils.GetDelegateTypeBasedOnMethodParameters(code.Method).AssemblyQualifiedNameCache(); stateManager.AddNewObject(promise); if (objectContainingMethod != null) { if (!StateManager.AllBranchesAttached(objectContainingMethod)) { stateManager.AdoptionInformation.RegisterPossibleOrphan(promise, objectContainingMethod); } var referenceToObjectContainingMethod = new StateObjectPointerReference(); var relativeUid = UniqueIDGenerator.GetPointerRelativeUniqueID(promise, "PO"); LazyBehaviours.AddDependent(promise, UniqueIDGenerator.REFERENCEPrefix + "PO"); StateObjectPointer.AssignUniqueIdToPointer(promise, relativeUid, referenceToObjectContainingMethod); referenceToObjectContainingMethod.Target = objectContainingMethod; stateManager.isServerSideOnly.Add(referenceToObjectContainingMethod); stateManager.AddNewObject(referenceToObjectContainingMethod); stateManager.ReferencesManager.AddReference(referenceToObjectContainingMethod, objectContainingMethod); var surrogate = objectContainingMethod as StateObjectSurrogate; if (surrogate != null) { stateManager.surrogateManager.AddSurrogateReference(surrogate, referenceToObjectContainingMethod); } promise.SetObjectContainingMethod(referenceToObjectContainingMethod); } if (parent != null && objectContainingMethod != null && parent.Equals(objectContainingMethod)) { promise.isLocalInstance = true; } else if (promiseUniqueId != null && objectContainingMethod != null) { var parentUniqueID = StateManager.GetLastPartOfUniqueID(promise); promise.isLocalInstance = string.Equals(parentUniqueID, objectContainingMethod.UniqueID); } return(promise); }
internal static object FromContinuationInfo(Type type, EventPromiseInfo promise, IStateObject source = null) { try { var methodDeclaringType = TypeCacheUtils.GetType(promise.DeclaringType); object targetInstance = null; Type[] types = Type.EmptyTypes; if (promise.MethodArgs != null) { var typesNames = promise.MethodArgs.Split(PIPE_SEPARATOR, StringSplitOptions.RemoveEmptyEntries); types = new Type[typesNames.Length]; int i = 0; foreach (var typeName in typesNames) { types[i++] = TypeCacheUtils.GetType(typeName); } } if (promise.isLocalInstance && source != null) { targetInstance = source; } else { var pointer = promise.ObjectContainingMethod as StateObjectPointerReference; if (pointer != null) { targetInstance = pointer.Target; } else { targetInstance = promise.ObjectContainingMethod; } } if (targetInstance is StateObjectSurrogate) { targetInstance = ((StateObjectSurrogate)targetInstance).Value; } if (targetInstance == null) { //Was this an static method? if (promise.TargetType == null) { //Yes static var staticType = TypeCacheUtils.GetType(promise.DeclaringType); var staticmethod = staticType.GetMethod(promise.MethodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); return(Delegate.CreateDelegate(type, staticmethod)); } else { //Ok, it was a not an IStateObject object. It might have been //a delegate from another class //So we need to instantiate it and set it to targetInstance var targetType = TypeCacheUtils.GetType(promise.TargetType); targetInstance = Activator.CreateInstance(targetType); if (promise.ContinuationFields != null) { //Pending Restore state } } } else { //First check if method was on this targetInstance. Why not? Because it could have been on a form if (typeof(ILogicView <IViewModel>).IsAssignableFrom(methodDeclaringType)) { var instanceWithMethodDeclaredType = TypeCacheUtils.GetType(promise.TargetType); var form = IocContainerImplWithUnity.Current.Resolve(instanceWithMethodDeclaredType, parameters: new object[] { (IViewModel)targetInstance }); targetInstance = form; } } var method = methodDeclaringType.GetMethod(promise.MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, new ReflectionBinderForPromisesResolution(), types, null); //If type is delegate then we must build a generic delegate from Action<> or Func<> helpers if (typeof(Delegate) == type) { Type methodDelegateType = TypeCacheUtils.GetDelegateTypeBasedOnMethodParameters(method); return(Delegate.CreateDelegate(methodDelegateType, targetInstance, method)); } return(Delegate.CreateDelegate(type, targetInstance, method)); } catch (Exception ex) { TraceUtil.TraceError("ViewManager::PromiseUtils::FromContinuationInfo error while trying to restore delegate from continuation " + ex.Message); } return(null); }