Skip to content

Resolvers

Axwabo edited this page Mar 23, 2025 · 2 revisions

Resolvers

Resolvers are used by the Axwabo.CommandSystem.Registration.CommandRegistrationProcessor during registration. They provide a way to separate the attribute data from the logic which gets the value for a property.

Most resolvers process a specific attribute. See also: instance-based resolvers

Tip

Resolvers can be incredibly useful if you want to specify multiple properties at once with an enum or a short string key, as shown in the example plugin

Various interfaces exist in the Axwabo.CommandSystem.PropertyManager.Resolvers namespace to resolve a property of a command or RA option. You must implement the generic interface to be able to use the resolver. See also: list of resolvers

Declaration

When passing a type or a member instance to CommandRegistrationProcessor.RegisterAll, the attributes on the type (or the type of the member) are added as resolver objects if applicable.

The Axwabo.CommandSystem.Registration.RegistrationExtensions class defines all extension methods that can be used on a CommandRegistrationProcessor to manually add resolvers. These methods can be chained as they return the processor that was passed in.

RegisterAll uses the WithMultiplexResolverObject extension method to add all applicable implemented resolvers of each attribute.

Example

Description Attribute

Assume you have the following attribute that you add to command classes:

using System;

[AttributeUsage(AttributeTargets.Class)]
public sealed class ConfiguredDescriptionAttribute : Attribute
{

    public string Key { get; }

    public ConfiguredDescriptionAttribute(string key) => Key = key;

}

Config

A configuration class for the plugin:

using System.Collections.Generic;

public sealed class MyConfig
{

    public Dictionary<string, string> DescriptionTranslations { get; set; } = new()
    {
        {"myCommand", "MyCommand's description"}
    };

}

Description Resolver

Note

Resolvers don't need to be attributes. When a resolver isn't an attribute on the type used for registration, it must be manually added as shown in methods 3 and 4 of the plugin in this example

To resolve descriptions from the config, define a resolver attribute as follows:

using System;
using Axwabo.CommandSystem.PropertyManager.Resolvers;

[AttributeUsage(AttributeTargets.Class)]
public sealed class ConfiguredDescriptionResolverAttribute : Attribute,
    ICommandDescriptionResolver<ConfiguredDescriptionAttribute> // attribute to resolve from
{

    public string ResolveDescription(ConfiguredDescriptionAttribute attribute)
    {
        var config = MyPlugin.Instance?.Config;
        if (config == null)
            return null;
        if (config.DescriptionTranslations.TryGetValue(attribute.Key, out var description))
            return description;
        return null;
    }

}

Plugin

Finally, register the commands in your plugin:

using Axwabo.CommandSystem.Registration;
using LabApi.Loader.Features.Plugins;

[ConfiguredDescriptionResolver] // added by RegisterAll
public sealed class MyPlugin : Plugin<MyConfig>
{

    // plugin properties

    public static MyPlugin Instance { get; private set; }

    public override void Enable()
    {
        Instance = this;

        // method 1
        CommandRegistrationProcessor.RegisterAll(this);

        // method 2 (same as RegisterAll)
        CommandRegistrationProcessor.Create(this)
            .WithTypesFromOriginalAssembly()
            .WithRegistrationAttributesFrom(GetType())
            .Execute();

        // method 3 processes a specific class,
        // adding all implemented resolvers 
        CommandRegistrationProcessor.Create(this)
            .WithTypesFromOriginalAssembly()
            .WithMultiplexResolverObject(new ConfiguredDescriptionResolverAttribute())
            .Execute();

        // method 4 explicitly sets what kind of resolvers to add,
        // even if a class implements multiple resolvers
        // the same instance may be reused in different calls
        CommandRegistrationProcessor.Create(this)
            .WithTypesFromOriginalAssembly()
            .WithDescriptionResolver(new ConfiguredDescriptionResolverAttribute())
            .Execute();
    }

    // unregister commands on disable

}

Resolver List

Important

The IAttributeBasedPermissionResolver is only invoked if no instance-based resolver could process the attribute.

Interface Method Name Return Type
IAffectedAllPlayersResolver ResolveGenerator IAffectedAllPlayersMessageGenerator
IAffectedMultiplePlayersResolver ResolveGenerator IAffectedMultiplePlayersMessageGenerator
IAffectedOnePlayerResolver ResolveGenerator IAffectedOnePlayerMessageGenerator
IAttributeBasedPermissionResolver ResolvePermissionChecker IPermissionChecker
ICommandAliasResolver ResolveAliases string[]
ICommandDescriptionResolver ResolveDescription string
ICommandNameResolver ResolveName string
ICommandUsageResolver ResolveUsage string[]
IOptionIconResolver ResolveIcon BlinkingIcon
IPlayerOnlyResolver ResolvePlayerOnly bool
IRemoteAdminOptionIdResolver ResolveIdentifier string
IResultCompilerResolver ResolveCompiler ICustomResultCompiler
IStaticOptionTextResolver ResolveContent string
ITargetSelectionResolver ResolveSelectionManager ITargetSelectionManager

Instance-Based Resolvers

Important

Instance-based resolvers must be implemented by an attribute that is placed on the type of the command or RA option

Instance-based resolvers operate on the command or RA option instance. They can be used to resolve a permission checker based on any factor, since base properties have already been initialized. This factor may be the command name or an enum defined in a custom command class.

When implementing the IInstanceBasedPermissionResolver interface, both of the following methods have to be declared:

  • CreateFromCommand(CommandBase)
  • CreateFromOption(RemoteAdminOptionBase)

The IGenericCommandInstanceBasedPermissionResolver<TCommand> and IGenericRemoteAdminOptionInstanceBasedPermissionResolver<TOption> interfaces only specify a Create method where the parameter is the type of TCommand or TOption, respectively.

Clone this wiki locally