question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

CreateModuleAsync in InteractionService cannot be used to create a buildable Module.

See original GitHub issue

The Problem:

CreateModuleAsync offers a BuilderAction, however, you cannot set the TypeInfo of the Module you want to build in the passed ModuleBuilder object. This results in a NullReferenceException when the builder is being built.

interactionService.CreateModuleAsync("name", serviceProvider, builder =>
{
    builder.TypeInfo = typeof(MyModule); // Not possible as the 'TypeInfo' property is marked internal.
});

The main problem is that the TypeInfo property is marked internal and there’s no way to provide a TypeInfo to the ModuleBuilder object externally.

Possible ways to fix this:

1. Add a Setter-Method to ModuleBuilder.

public ModuleBuilder WithTypeInfo(TypeInfo typeInfo)
{
    TypeInfo = typeInfo;
    return this;
}
Possible Problems:

The TypeInfo may be invalid. As validity checks are normally done in the ModuleClassBuilder type, a duplicate check or a reference to ModuleClassBuilder would have to be added.

2. Pass the TypeInfo from the CreateModuleAsync method and instantiate the ModuleBuilder via the ModuleClassBuilder.

In InteractionService:

public async Task<ModuleInfo> CreateModuleAsync(string name, TypeInfo typeInfo, IServiceProvider services,
    Action<ModuleBuilder> buildFunc)
{
    // ...
    try
    {
        var moduleInfo = ModuleClassBuilder.CreateModuleAsync(name, typeInfo, buildFunc, this, services);
        LoadModuleInternal(moduleInfo);

        return moduleInfo;
    }
    // ...
}

In ModuleClassBuilder:

public static ModuleInfo CreateModuleAsync(string name, TypeInfo typeInfo, Action<ModuleBuilder> buildFunc,
    InteractionService interactionService, IServiceProvider services)
{
    if (!IsValidModuleDefinition(typeInfo))
        throw new InvalidOperationException();

    var builder = new ModuleBuilder(interactionService);
    builder.TypeInfo = typeInfo; // Set TypeInfo here after it has been checked.

    buildFunc(builder);
    var moduleInfo = builder.Build(interactionService, services);

    return moduleInfo;
}
Possible Problems:

This would most likely be a breaking change as the signature of CreateModuleAsync would need to be changed to accommodate the TypeInfo parameter. But seeing as the method can’t be used anyway, this might be the cleanest way to handle this.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:9

github_iconTop GitHub Comments

1reaction
Cenngocommented, Dec 26, 2021

Probably going to introduce a new Construct method for performing this task.

1reaction
Cenngocommented, Dec 26, 2021

CreateModuleAsync method isn’t meant to be used with reflection so setting TypeInfo on its own wouldnt accomplish much aside from solving the NRE. Instead, we can just add a null check and method validation before executing Module.OnModuleBuilding.

if(TypeInfo is not null && ModuleClassBuilder.IsValidModuleDefinition(TypeInfo))

Great issue btw.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Top-level 'await' expressions are only allowed when the ' ...
This is a workaround showing the user how to avoid using top level await, rather than an answer.
Read more >
Introduction to the Interaction Service
Every command module exposes a set of helper methods, namely: RespondAsync() => Respond to the interaction; FollowupAsync() => Create a followup message for ......
Read more >
Asynchronous support
Any view can be declared async by making the callable part of it return a coroutine - commonly, this is done using async...
Read more >
Build an async python service with FastAPI & SQLAlchemy
Build a fully asynchronous python service, including async DB queries, using FastAPI and the new SQLAlchemy AsyncIO support.
Read more >
Dynamic modules | NestJS - A progressive Node.js ...
As manually creating highly configurable, dynamic modules that expose async methods ( registerAsync , forRootAsync , etc.) is quite complicated, especially for ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found