123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- using Wayne.Lib.StateEngine.Generic;
- using System.Diagnostics;
- namespace Wayne.Lib.StateEngine
- {
- /// <summary>
- /// State factory with the Main object T
- /// </summary>
- /// <typeparam name="T"></typeparam>
- public class StateFactory<T> : IStateFactory2
- {
- private readonly Func<T> main;
- private readonly IServiceLocator serviceContainer;
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="main"></param>
- /// <param name="serviceContainer"></param>
- public StateFactory(T main, IServiceLocator serviceContainer)
- {
- this.main = () => main;
- this.serviceContainer = serviceContainer;
- }
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="mainFunc"></param>
- /// <param name="serviceContainer"></param>
- public StateFactory(Func<T> mainFunc, IServiceLocator serviceContainer)
- {
- this.main = mainFunc;
- this.serviceContainer = serviceContainer;
- }
- #region Implementation of IStateFactory
- /// <summary>
- /// Tries to create the requested state
- /// </summary>
- /// <param name="stateFactoryName"></param>
- /// <returns></returns>
- public State CreateState(string stateFactoryName)
- {
- throw new InvalidOperationException("Use CreateState with StateTypeContainer");
- }
- private State TryCreate(Type stateType)
- {
- var constructors = stateType.GetConstructors();
- var lastConstructor = constructors[constructors.Length - 1];
- var parameterInfos = lastConstructor.GetParameters();
- List<object> parameters = new List<object>();
- foreach (var parameterInfo in parameterInfos)
- {
- try
- {
- parameters.Add(serviceContainer.GetService(parameterInfo.ParameterType));
- }
- catch (ServiceContainerException ex)
- {
- Debug.WriteLine(string.Format("Creating state {0} because its dependency {1} could not be found in the container. Error message : {2}", stateType, parameterInfo.ParameterType, ex.Message));
- throw;
- }
- }
- var stateObject = lastConstructor.Invoke(parameters.ToArray());
- return stateObject as State;
- }
- /// <summary>
- /// Prepare a state with a Main object if it has got one.
- /// </summary>
- /// <param name="stateObject"></param>
- protected virtual void PrepareState(object stateObject)
- {
- IGenericState<T> genericClientState = stateObject as IGenericState<T>;
- if (genericClientState != null)
- genericClientState.WritableMain = main();
- }
- /// <summary>
- /// Name of the State Factory
- /// </summary>
- public string Name
- {
- get { return GetType().Name; }
- }
- /// <summary>
- /// Creates the given state using the supplied StateTypeContainer
- /// </summary>
- /// <param name="stateFactoryName"></param>
- /// <param name="stateTypeContainer"></param>
- /// <returns></returns>
- public State CreateState(string stateFactoryName, StateTypeContainer stateTypeContainer)
- {
- Type stateType;
- if (stateTypeContainer.TryGetStateType(stateFactoryName, out stateType))
- {
- //Check if Main is of same type as T.
- List<Type> ancestry = new List<Type>();
- var mainObjectValue = main();
- Type type = mainObjectValue.GetType();
- do
- {
- ancestry.Add(type);
- type = type.BaseType;
- } while (type != typeof(object));
- State state = TryCreate(stateType);
- foreach (Type t in ancestry)
- {
- Type genericType = typeof(IGenericState<>);
- Type actualType = genericType.MakeGenericType(t);
- if (actualType.IsInstanceOfType(state))
- {
- PropertyInfo propertyInfo = actualType.GetProperty("WritableMain");
- propertyInfo.SetValue(state, mainObjectValue, new object[] { });
- }
- }
- return state;
- }
- return null;
- }
- #endregion
- }
- }
|