|  | @@ -23,10 +23,15 @@ namespace InABox.Core
 | 
	
		
			
				|  |  |              return settings;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        private static PostableSettings LoadPostableSettings(Type T)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return FixPostableSettings(T, new GlobalConfiguration<PostableSettings>(T.Name).Load());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          public static PostableSettings LoadPostableSettings<T>()
 | 
	
		
			
				|  |  |              where T : Entity, IPostable
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            return FixPostableSettings(typeof(T), new GlobalConfiguration<PostableSettings>(typeof(T).Name).Load());
 | 
	
		
			
				|  |  | +            return LoadPostableSettings(typeof(T));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          public static void SavePostableSettings<T>(PostableSettings settings)
 | 
	
	
		
			
				|  | @@ -140,6 +145,10 @@ namespace InABox.Core
 | 
	
		
			
				|  |  |              return GetPosters().Where(x => TPoster.IsAssignableFrom(x)).FirstOrDefault()
 | 
	
		
			
				|  |  |                  ?? throw new Exception($"No poster of type {TPoster}.");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        public static Type? GetPoster(string posterType)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return GetPosters()?.FirstOrDefault(x => x.EntityName() == posterType)!;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          private static EngineType[] GetPosterEngines()
 | 
	
		
			
				|  |  |          {
 | 
	
	
		
			
				|  | @@ -149,43 +158,71 @@ namespace InABox.Core
 | 
	
		
			
				|  |  |                      && !x.IsAbstract
 | 
	
		
			
				|  |  |                      && x.GetTypeInfo().GenericTypeParameters.Length == 1
 | 
	
		
			
				|  |  |                      && x.HasInterface(typeof(IPosterEngine<,,>))
 | 
	
		
			
				|  |  | -            ).Select(x => new EngineType
 | 
	
		
			
				|  |  | +            ).Select(x =>
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                Engine = x,
 | 
	
		
			
				|  |  | -                Entity = x.GetInterfaceDefinition(typeof(IPosterEngine<,,>))!.GenericTypeArguments[0],
 | 
	
		
			
				|  |  | -                Poster = x.GetInterfaceDefinition(typeof(IPosterEngine<,,>))!.GenericTypeArguments[1].GetGenericTypeDefinition()
 | 
	
		
			
				|  |  | +                var poster = x.GetInterfaceDefinition(typeof(IPosterEngine<,,>))!.GenericTypeArguments[1];
 | 
	
		
			
				|  |  | +                return new EngineType
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    Engine = x,
 | 
	
		
			
				|  |  | +                    Entity = x.GetInterfaceDefinition(typeof(IPosterEngine<,,>))!.GenericTypeArguments[0],
 | 
	
		
			
				|  |  | +                    Poster = poster.IsGenericType ? poster.GetGenericTypeDefinition() : poster
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  |              }).ToArray();
 | 
	
		
			
				|  |  |              return _posterEngines;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  | -        /// Get the <see cref="IPosterEngine{TPostable,TPoster,TSettings}"/> for <typeparamref name="T"/>
 | 
	
		
			
				|  |  | -        /// based on the current <see cref="PostableSettings"/> for <typeparamref name="T"/>.
 | 
	
		
			
				|  |  | +        /// Get the <see cref="IPosterEngine{TPostable,TPoster,TSettings}"/> for <paramref name="T"/>
 | 
	
		
			
				|  |  | +        /// based on the current <see cref="PostableSettings"/> for <paramref name="T"/>.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  | -        /// <typeparam name="T"></typeparam>
 | 
	
		
			
				|  |  |          /// <returns></returns>
 | 
	
		
			
				|  |  | -        public static Type GetEngine<T>()
 | 
	
		
			
				|  |  | -            where T : Entity, IPostable, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +        public static Result<Type, Exception> GetEngine(Type T)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var settings = LoadPostableSettings<T>();
 | 
	
		
			
				|  |  | +            var settings = LoadPostableSettings(T);
 | 
	
		
			
				|  |  |              if (string.IsNullOrWhiteSpace(settings.PosterType))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                throw new MissingSettingsException(typeof(T));
 | 
	
		
			
				|  |  | +                return Result.Error<Exception>(new MissingSettingsException(T));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            var poster = GetPoster(settings.PosterType);
 | 
	
		
			
				|  |  | +            if(poster is null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return Result.Error(new Exception($"No poster of type {settings.PosterType}."));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            var poster = GetPosters()?.FirstOrDefault(x => x.EntityName() == settings.PosterType)!;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var engines = GetPosterEngines().Where(x => poster.HasInterface(x.Poster)).ToList();
 | 
	
		
			
				|  |  | +            var engines = GetPosterEngines().Where(x =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return x.Poster.IsInterface ? poster.HasInterface(x.Poster) : poster.IsSubclassOfRawGeneric(x.Poster);
 | 
	
		
			
				|  |  | +            }).ToList();
 | 
	
		
			
				|  |  |              if (!engines.Any())
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                throw new Exception("No poster for the given settings.");
 | 
	
		
			
				|  |  | +                return Result.Error(new Exception("No poster for the given settings"));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              else if(engines.Count == 1)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                return engines[0].Engine.MakeGenericType(typeof(T));
 | 
	
		
			
				|  |  | +                return Result.Ok(engines[0].Engine.MakeGenericType(T));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              else
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                return engines.Single(x => x.Entity == typeof(T)).Engine.MakeGenericType(typeof(T));
 | 
	
		
			
				|  |  | +                return Result.Ok(engines.Single(x => x.Entity == T).Engine.MakeGenericType(T));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Get the <see cref="IPosterEngine{TPostable,TPoster,TSettings}"/> for <typeparamref name="T"/>
 | 
	
		
			
				|  |  | +        /// based on the current <see cref="PostableSettings"/> for <typeparamref name="T"/>.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <typeparam name="T"></typeparam>
 | 
	
		
			
				|  |  | +        /// <returns></returns>
 | 
	
		
			
				|  |  | +        public static Type GetEngine<T>()
 | 
	
		
			
				|  |  | +            where T : Entity, IPostable, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (GetEngine(typeof(T)).Get(out var engineType, out var e))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return engineType;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw e;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -226,7 +263,7 @@ namespace InABox.Core
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  return false;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            var poster = GetPosters()?.FirstOrDefault(x => x.EntityName() == settings.PosterType);
 | 
	
		
			
				|  |  | +            var poster = GetPoster(settings.PosterType);
 | 
	
		
			
				|  |  |              if (poster is null)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  return false;
 | 
	
	
		
			
				|  | @@ -235,7 +272,7 @@ namespace InABox.Core
 | 
	
		
			
				|  |  |              if(iautoRefresh != null)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  var autoRefresher = Activator.CreateInstance(iautoRefresh.GenericTypeArguments[1]) as IAutoRefresher<T>;
 | 
	
		
			
				|  |  | -                if (autoRefresher != null && autoRefresher.ShouldRepost(item))
 | 
	
		
			
				|  |  | +                if (autoRefresher != null && autoRefresher.ShouldRepost(item!))
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      postable.PostedStatus = PostedStatus.RequiresRepost;
 | 
	
		
			
				|  |  |                      return true;
 | 
	
	
		
			
				|  | @@ -266,6 +303,34 @@ namespace InABox.Core
 | 
	
		
			
				|  |  |              return CreateEngine<T>().Process(model);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Import <typeparamref name="T"/> with the currently set <see cref="IPosterEngine{TPostable, TPoster, TSettings}"/>.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <typeparam name="T"></typeparam>
 | 
	
		
			
				|  |  | +        /// <returns><see langword="null"/> if post was unsuccessful.</returns>
 | 
	
		
			
				|  |  | +        /// <exception cref="InvalidPullerException">If the engine is not a <see cref="IPullerEngine{TPostable,TPoster}"/></exception>
 | 
	
		
			
				|  |  | +        public static IPullResult<T>? Pull<T>()
 | 
	
		
			
				|  |  | +            where T : Entity, IPostable, IRemotable, IPersistent, new()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var engine = CreateEngine<T>();
 | 
	
		
			
				|  |  | +            if(engine is IPullerEngine<T> puller)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return puller.Pull();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var intDef = engine.GetType().GetInterfaceDefinition(typeof(IPosterEngine<,,>));
 | 
	
		
			
				|  |  | +                if(intDef != null)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new InvalidPullerException(typeof(T), intDef.GenericTypeArguments[1]);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                else
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    throw new InvalidPullerException(typeof(T));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          #endregion
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |