public void Register <T, TC, TE, TS>(Func <T> entityFactory)
            where T : ShardedEntity <TC, TE, TS>
            where TC : AbstractCommand
            where TE : AbstractEvent
            where TS : AbstractState
        {
            var proto           = entityFactory.Invoke();
            var entityTypeName  = proto.EntityTypeName;
            var entityClassType = proto.GetType();

            var alreadyRegistered = RegisteredTypeNames.GetOrAdd(entityTypeName, entityClassType);

            if (alreadyRegistered != null && alreadyRegistered != entityClassType)
            {
                throw new InvalidOperationException($"The entity type {nameof(T)} is already registered");
            }

            ReverseRegister.TryAdd(entityClassType, entityTypeName);

            var PassivateAfterIdleTimeout = ActorSystem.Settings.Config.GetConfig("wyvern.persistence")
                                            .GetTimeSpan("passivate-after-idle-timeout", TimeSpan.FromSeconds(100));

            const string snapshotPluginId = "";
            const string journalPluginId  = "";

            JoinCluster(ActorSystem);

            if (Role.ForAll(Cluster.Get(ActorSystem).SelfRoles.Contains))
            {
                ActorSystem.Log.Info("Cluster sharding initialized");
                var props = ShardedEntityActorProps.Create <T, TC, TE, TS>(
                    entityTypeName,
                    Option <string> .None,
                    entityFactory,
                    SnapshotAfter,
                    PassivateAfterIdleTimeout,
                    snapshotPluginId,
                    journalPluginId
                    );

                Sharding.Start(
                    entityTypeName,
                    props,
                    ShardingSettings,
                    ExtractEntityId,
                    ExtractShardId
                    );
            }
            else
            {
                ActorSystem.Log.Warning("Cluster proxy initialized");
                Sharding.StartProxy(
                    entityTypeName,
                    Role.Value,
                    ExtractEntityId,
                    ExtractShardId
                    );
            }
        }