private void RegisterSpellTargetSelectors([NotNull] ActorAssemblyDefinitionConfiguration actorAssemblyConfig, [NotNull] ContainerBuilder builder) { if (actorAssemblyConfig == null) { throw new ArgumentNullException(nameof(actorAssemblyConfig)); } if (builder == null) { throw new ArgumentNullException(nameof(builder)); } //SingletonSpellEffectTargetSelectorFactory : ISpellEffectTargetSelectorFactory builder.RegisterType <SingletonSpellEffectTargetSelectorFactory>() .As <ISpellEffectTargetSelectorFactory>() .SingleInstance(); foreach (Assembly assemblyToParse in actorAssemblyConfig.AssemblyNames .Select(d => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => d == a.GetName().Name.ToLower())) .Where(a => a != null)) { foreach (Type t in assemblyToParse.GetTypes()) { //If they have the handler attribute, we should just register it. if (typeof(ISpellEffectTargetSelector).IsAssignableFrom(t) && t.GetCustomAttributes <SpellEffectTargetingStrategyAttribute>().Any() && !t.IsAbstract) { builder.RegisterType(t) .As <ISpellEffectTargetSelector>() .SingleInstance(); } } } }
private void RegisterSpellCastAttemptValidators(ActorAssemblyDefinitionConfiguration actorAssemblyConfig, ContainerBuilder builder) { //SingletonSpellCastAttemptValidator : ISpellCastAttemptValidator builder.RegisterType <SingletonSpellCastAttemptValidator>() .As <ISpellCastAttemptValidator>() .SingleInstance(); foreach (Assembly assemblyToParse in actorAssemblyConfig.AssemblyNames .Select(d => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => d == a.GetName().Name.ToLower())) .Where(a => a != null)) { foreach (Type t in assemblyToParse.GetTypes()) { //If they have the handler attribute, we should just register it. if (typeof(ISpellCastValidator).IsAssignableFrom(t) && t.GetCustomAttributes <SpellCastValidatorAttribute>().Any() && !t.IsAbstract) { builder.RegisterType(t) .As <ISpellCastValidator>() .SingleInstance(); } } } }
protected override void Load([NotNull] ContainerBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } //TODO: Expose and register this as appart of configuration system ActorAssemblyDefinitionConfiguration actorAssemblyConfig = new ActorAssemblyDefinitionConfiguration(Array.Empty <string>()); RegisterSpellTargetValidators(actorAssemblyConfig, builder); RegisterSpellTargetSelectors(actorAssemblyConfig, builder); RegisterSpellEffectHandlers(actorAssemblyConfig, builder); RegisterSpellCastAttemptValidators(actorAssemblyConfig, builder); //EffectTargetSelectorRoutedSpellCastDispatcher builder.RegisterType <EffectTargetSelectorRoutedSpellCastDispatcher>() .As <ISpellCastDispatcher>() .SingleInstance(); //DefaultPendingSpellCastFactory : IPendingSpellCastFactory builder.RegisterType <DefaultPendingSpellCastFactory>() .As <IPendingSpellCastFactory>() .SingleInstance(); //DefaultSpellEffectApplicationMessageFactory : ISpellEffectApplicationMessageFactory builder.RegisterType <DefaultSpellEffectApplicationMessageFactory>() .As <ISpellEffectApplicationMessageFactory>() .SingleInstance(); //DefaultLearnedSpellsCollection : ILearnedSpellsCollection, IReadonlyLearnedSpellsCollection builder.RegisterType <DefaultLearnedSpellsCollection>() .As <ILearnedSpellsCollection>() .As <IReadonlyLearnedSpellsCollection>() .SingleInstance(); }
protected override void Load(ContainerBuilder builder) { //TODO: Expose and register this as appart of configuration system ActorAssemblyDefinitionConfiguration actorAssemblyConfig = new ActorAssemblyDefinitionConfiguration(Array.Empty <string>()); foreach (var s in actorAssemblyConfig.AssemblyNames) { Debug.Log($"Actor Assembly: {s}"); } Debug.Log(AppDomain.CurrentDomain.GetAssemblies().Aggregate("Loaded Assemblies: ", (s, assembly) => $"{s} {assembly.GetName().Name}")); //The below loads the actor assemblies defined in the configuration. //It then searches for all message handlers and then registers them. //It's a complicated process. //TODO: Support actually loading unloaded assemblies (like 3rd party user assemblies) foreach (Assembly actorAssemblyToParse in actorAssemblyConfig.AssemblyNames .Select(d => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => d == a.GetName().Name.ToLower())) .Where(a => a != null)) { Debug.Log($"Parsing ActorAssembly: {actorAssemblyToParse.GetName().Name}"); foreach (Type t in actorAssemblyToParse.GetTypes()) { //If they have the handler attribute, we should just register it. if (t.GetCustomAttributes <EntityActorMessageHandlerAttribute>().Any()) { Debug.Log($"Register ActorMessageHandler: {t.Name}"); //Now we need to find the actor state type Type actorStateType = t.GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityActorMessageHandler <,>)) .GenericTypeArguments.First(); var handlerRegisteration = builder.RegisterType(t) .AsSelf() .As(typeof(IEntityActorMessageHandler <,>).MakeGenericType(new Type[2] { actorStateType, typeof(EntityActorMessage) })) .As <IEntityActorMessageHandler>() .SingleInstance(); foreach (var attri in t.GetCustomAttributes <EntityActorMessageHandlerAttribute>()) { //TODO: Support multiple level inherited types. //If the actor has a different state type we should assume it's valid if it can be assigned. Type specificActorStateType = attri.TargetActorType.BaseType.GenericTypeArguments.Reverse().First(); if (specificActorStateType != actorStateType) { if (actorStateType.IsAssignableFrom(specificActorStateType)) { handlerRegisteration = handlerRegisteration .As(typeof(IEntityActorMessageHandler <,>).MakeGenericType(new Type[2] { specificActorStateType, typeof(EntityActorMessage) })); } else { throw new InvalidOperationException($"Actor: {attri.TargetActorType.Name} attempted to use Handler: {t.Name} but had non-matching state Types: {actorStateType.Name}/{specificActorStateType.Name}"); } } } } else if (typeof(IEntityActor).IsAssignableFrom(t)) { //Don't want to register abstract entities. if (!t.IsAbstract) { Debug.Log($"Register Actor: {t.Name}"); builder.RegisterType(t) .AsSelf(); } } } } //Below is an open generic registeration of the generic router //this makes it EASY to inject into the actors builder.RegisterGeneric(typeof(ReflectionBasedGenericMessageRouter <,>)) .As(typeof(IEntityActorMessageRouteable <,>)) .SingleInstance(); //Create the root of the actor system. builder.RegisterInstance(ActorSystem.Create("Root")) .AsSelf() .As <ActorSystem>() .As <IActorRefFactory>() .SingleInstance(); builder.Register <IScheduler>(context => { ActorSystem actorSystem = context.Resolve <ActorSystem>(); return(actorSystem.Scheduler); }) .As <IScheduler>() .SingleInstance(); //Creates the autofac dependency resolver that can be used to actually resolve //the Actor's dependencies. builder.Register(context => { if (!context.IsRegistered <IEntityActorMessageRouteable <DefaultWorldActor, WorldActorState> >()) { Debug.LogError($"CRITICAL dependency for Actor IOC not registered."); } if (!context.IsRegistered <DefaultWorldActor>()) { Debug.LogError($"CRITICAL dependency for Actor IOC not registered."); } return(new AutoFacDependencyResolver(context.Resolve <ILifetimeScope>(), context.Resolve <ActorSystem>())); }) .As <IDependencyResolver>() .AsSelf() .SingleInstance(); builder.RegisterType <DefaultWorldActor>() .AsSelf(); builder.RegisterType <UnityAkkaActorLoggerAdapter>() .AsSelf() .As <ILoggingAdapter>() .SingleInstance(); builder.RegisterType <UnityLoggerActor>() .AsSelf(); builder.RegisterType <DefaultGameObjectEntityActorFactory>() .As <IGameObjectEntityActorFactory>() .SingleInstance(); //This creates the World actor. builder.Register(context => { try { IDependencyResolver resolver = context.Resolve <IDependencyResolver>(); ActorSystem actorSystem = context.Resolve <ActorSystem>(); actorSystem.ActorOf(resolver.Create <UnityLoggerActor>(), "Logger"); IActorRef worldActorReference = actorSystem.ActorOf(resolver.Create <DefaultWorldActor>(), "World"); if (worldActorReference.IsNobody()) { Debug.LogError($"FAILED TO CREATE WORLD ACTOR."); } return(new WorldActorReferenceAdapter(worldActorReference)); } catch (Exception e) { Debug.LogError($"Failed to create WorldActor in IoC. Reason: {e.Message}\n\nStack: {e.StackTrace}"); throw; } }) .As <IWorldActorRef>() .SingleInstance(); }