/// <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);
        }
示例#3
0
        /// <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);
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }