Exemplo n.º 1
0
        /// <summary>
        /// Initializes information about the states of the monitor.
        /// </summary>
        private void InitializeStateInformation()
        {
            this.StateTypes = new HashSet <Type>();
            this.States     = new HashSet <MonitorState>();

            Type monitorType      = this.GetType();
            Type initialStateType = null;

            while (monitorType != typeof(Monitor))
            {
                foreach (var s in monitorType.GetNestedTypes(BindingFlags.Instance |
                                                             BindingFlags.NonPublic | BindingFlags.Public |
                                                             BindingFlags.DeclaredOnly))
                {
                    if (s.IsClass && s.IsSubclassOf(typeof(MonitorState)))
                    {
                        if (s.IsDefined(typeof(Start), false))
                        {
                            this.Assert(initialStateType == null, "Monitor '{0}' can not have " +
                                        "more than one start states.\n", this.GetType().Name);
                            initialStateType = s;
                        }

                        this.Assert(s.BaseType == typeof(MonitorState), "State '{0}' is " +
                                    "not of the correct type.\n", s.Name);
                        this.StateTypes.Add(s);
                    }
                }

                monitorType = monitorType.BaseType;
            }

            foreach (var type in this.StateTypes)
            {
                var isHot  = false;
                var isCold = false;

                var hotAttribute = type.GetCustomAttribute(typeof(Hot), false) as Hot;
                if (hotAttribute != null)
                {
                    isHot = true;
                }

                var coldAttribute = type.GetCustomAttribute(typeof(Cold), false) as Cold;
                if (coldAttribute != null)
                {
                    isCold = true;
                }

                MonitorState state = Activator.CreateInstance(type) as MonitorState;
                state.InitializeState(this, isHot, isCold);

                this.States.Add(state);
            }

            var initialState = this.States.First(val => val.GetType().Equals(initialStateType));

            this.ConfigureStateTransitions(initialState);
            this.State = initialState;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Initializes information about the states of the monitor.
        /// </summary>
        internal void InitializeStateInformation()
        {
            Type monitorType = this.GetType();

            // Caches the available state types for this monitor type.
            if (StateTypeMap.TryAdd(monitorType, new HashSet <Type>()))
            {
                Type baseType = monitorType;
                while (baseType != typeof(Monitor))
                {
                    foreach (var s in baseType.GetNestedTypes(BindingFlags.Instance |
                                                              BindingFlags.NonPublic | BindingFlags.Public |
                                                              BindingFlags.DeclaredOnly))
                    {
                        this.ExtractStateTypes(s);
                    }

                    baseType = baseType.BaseType;
                }
            }

            // Caches the available state instances for this monitor type.
            if (StateMap.TryAdd(monitorType, new HashSet <MonitorState>()))
            {
                foreach (var type in StateTypeMap[monitorType])
                {
                    Type stateType = type;
                    if (type.IsAbstract)
                    {
                        continue;
                    }

                    if (type.IsGenericType)
                    {
                        // If the state type is generic (only possible if inherited by a
                        // generic monitor declaration), then iterate through the base
                        // monitor classes to identify the runtime generic type, and use
                        // it to instantiate the runtime state type. This type can be
                        // then used to create the state constructor.
                        Type declaringType = this.GetType();
                        while (!declaringType.IsGenericType ||
                               !type.DeclaringType.FullName.Equals(declaringType.FullName.Substring(
                                                                       0, declaringType.FullName.IndexOf('['))))
                        {
                            declaringType = declaringType.BaseType;
                        }

                        if (declaringType.IsGenericType)
                        {
                            stateType = type.MakeGenericType(declaringType.GetGenericArguments());
                        }
                    }

                    ConstructorInfo constructor = stateType.GetConstructor(Type.EmptyTypes);
                    var             lambda      = Expression.Lambda <Func <MonitorState> >(
                        Expression.New(constructor)).Compile();
                    MonitorState state = lambda();

                    state.InitializeState();

                    this.Assert((state.IsCold && !state.IsHot) ||
                                (!state.IsCold && state.IsHot) ||
                                (!state.IsCold && !state.IsHot),
                                $"State '{type.FullName}' of monitor '{this.Id}' " +
                                "cannot be both cold and hot.");

                    StateMap[monitorType].Add(state);
                }
            }

            // Caches the actions declarations for this monitor type.
            if (MonitorActionMap.TryAdd(monitorType, new Dictionary <string, MethodInfo>()))
            {
                foreach (var state in StateMap[monitorType])
                {
                    if (state.EntryAction != null &&
                        !MonitorActionMap[monitorType].ContainsKey(state.EntryAction))
                    {
                        MonitorActionMap[monitorType].Add(state.EntryAction,
                                                          this.GetActionWithName(state.EntryAction));
                    }

                    if (state.ExitAction != null &&
                        !MonitorActionMap[monitorType].ContainsKey(state.ExitAction))
                    {
                        MonitorActionMap[monitorType].Add(state.ExitAction,
                                                          this.GetActionWithName(state.ExitAction));
                    }

                    foreach (var transition in state.GotoTransitions)
                    {
                        if (transition.Value.Lambda != null &&
                            !MonitorActionMap[monitorType].ContainsKey(transition.Value.Lambda))
                        {
                            MonitorActionMap[monitorType].Add(transition.Value.Lambda,
                                                              this.GetActionWithName(transition.Value.Lambda));
                        }
                    }

                    foreach (var action in state.ActionBindings)
                    {
                        if (!MonitorActionMap[monitorType].ContainsKey(action.Value.Name))
                        {
                            MonitorActionMap[monitorType].Add(action.Value.Name,
                                                              this.GetActionWithName(action.Value.Name));
                        }
                    }
                }
            }

            // Populates the map of actions for this monitor instance.
            foreach (var kvp in MonitorActionMap[monitorType])
            {
                this.ActionMap.Add(kvp.Key, kvp.Value);
            }

            var initialStates = StateMap[monitorType].Where(state => state.IsStart).ToList();

            this.Assert(initialStates.Count != 0, $"Monitor '{this.Id}' must declare a start state.");
            this.Assert(initialStates.Count == 1, $"Monitor '{this.Id}' " +
                        "can not declare more than one start states.");

            this.ConfigureStateTransitions(initialStates.Single());
            this.State = initialStates.Single();

            this.AssertStateValidity();
        }