Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.TypeLoadException with generic attribute on C# model (dotnet-typegen 5.0.1) #202

Open
DBalashov opened this issue Jun 18, 2024 · 1 comment

Comments

@DBalashov
Copy link

I use generic attribute on models for FluentValidation.Auto package with automatic model validation

Model:

[ExportTsInterface]
[Validator<UserWalletValidator>]
public sealed record JUserWalletEditable(int ID, string Name, string Address);
sealed class UserWalletValidator : AbstractValidator<JUserWalletEditable>
{
    static readonly Regex addressValidator = new("^T[A-Za-z1-9]{33,35}$");
    
    public UserWalletValidator()
    {
        RuleFor(f => f.Name).NotEmpty().MinimumLength(4).MaximumLength(64);
        RuleFor(f => f.Address).NotEmpty()
                               .MaximumLength(36)
                               .Custom((s, ctx) =>
                                       {
                                           if (!addressValidator.IsMatch(s))
                                               ctx.AddFailure("Invalid TRC20 address");
                                       });
    }
}

Run dotnet-typegen generate -c tgconfig.json and exception occured:

Generating files for project "."...
Unhandled exception: System.TypeLoadException: GenericArguments[0], 'User.Services.Validators.UserWalletValidator', on 'FluentValidation.Auto.ValidatorAttribute`1[T]' violates the constraint of type parameter 'T'.
   at System.ModuleHandle.ResolveType(QCallModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
   at System.ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
   at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
   at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg)
   at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit)
   at System.Attribute.GetCustomAttributes(MemberInfo element, Type attributeType, Boolean inherit)
   at System.Attribute.GetCustomAttribute(MemberInfo element, Type attributeType, Boolean inherit)
   at System.Reflection.CustomAttributeExtensions.GetCustomAttribute[T](MemberInfo element)
   at TypeGen.Core.Metadata.AttributeMetadataReader.GetAttribute[TAttribute](Type type) in C:\projects\typegen\src\TypeGen\TypeGen.Core\Metadata\AttributeMetadataReader.cs:line 13
   at TypeGen.Core.Extensions.TypeExtensions.HasExportAttribute(Type type, IMetadataReader reader) in C:\projects\typegen\src\TypeGen\TypeGen.Core\Extensions\TypeExtensions.cs:line 27
   at TypeGen.Core.Extensions.TypeExtensions.<>c__DisplayClass1_0.<GetExportMarkedTypes>b__0(Type t) in C:\projects\typegen\src\TypeGen\TypeGen.Core\Extensions\TypeExtensions.cs:line 43
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at TypeGen.Core.Generator.Services.GenerationSpecProvider.GetGenerationSpec(IEnumerable`1 assemblies) in C:\projects\typegen\src\TypeGen\TypeGen.Core\Generator\Services\GenerationSpecProvider.cs:line 28
   at TypeGen.Core.Generator.Generator.Generate(IEnumerable`1 assemblies) in C:\projects\typegen\src\TypeGen\TypeGen.Core\Generator\Generator.cs:line 220
   at TypeGen.Cli.Ui.Presenter.GenerateSingle(String projectFolder, String configPath, String outputFolder) in C:\projects\typegen\src\TypeGen\TypeGen.Cli\Ui\Presenter.cs:line 108
   at TypeGen.Cli.Ui.Presenter.GeneratePrivate(Boolean verbose, IReadOnlyCollection`1 projectFolderPaths, IReadOnlyCollection`1 configPaths, String outputFolder) in C:\projects\typegen\src\TypeGen\TypeGen.Cli\Ui\Presenter.cs:line 78
   at TypeGen.Cli.Ui.Presenter.<>c__DisplayClass9_0.<Generate>b__0() in C:\projects\typegen\src\TypeGen\TypeGen.Cli\Ui\Presenter.cs:line 61
   at TypeGen.Cli.Ui.Validation.ValidationResult.Match(Action onSuccess, Action`1 onFailure) in C:\projects\typegen\src\TypeGen\TypeGen.Cli\Ui\Validation\ValidationResult.cs:line 32
   at TypeGen.Cli.Ui.Presenter.Generate(Boolean verbose, IReadOnlyCollection`1 projectFolderPaths, IReadOnlyCollection`1 configPaths, String outputFolder) in C:\projects\typegen\src\TypeGen\TypeGen.Cli\Ui\Presenter.cs:line 59
   at TypeGen.Cli.Application.<BuildCommandLine>b__5_1(Boolean v, List`1 p, List`1 c, String o) in C:\projects\typegen\src\TypeGen\TypeGen.Cli\Application.cs:line 98
   at System.CommandLine.Handler.<>c__DisplayClass5_0`4.<SetHandler>b__0(InvocationContext context)
   at System.CommandLine.Invocation.AnonymousCommandHandler.Invoke(InvocationContext context)
   at System.CommandLine.Invocation.AnonymousCommandHandler.InvokeAsync(InvocationContext context)
   at System.CommandLine.Invocation.InvocationPipeline.<>c__DisplayClass4_0.<<BuildInvocationChain>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass17_0.<<UseParseErrorReporting>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass12_0.<<UseHelp>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass22_0.<<UseVersionOption>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass19_0.<<UseTypoCorrections>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseSuggestDirective>b__18_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass16_0.<<UseParseDirective>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<RegisterWithDotnetSuggest>b__5_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass8_0.<<UseExceptionHandler>b__0>d.MoveNext()                                                                                                                                                                                                                                  

Config file:

{
    "assemblies": [
        "../Authentication.Services/bin/Debug/net8.0/Authentication.Services.dll",
        "../Common.Services/bin/Debug/net8.0/Common.Services.dll",
        "../DataLayer/bin/Debug/net8.0/DataLayer.dll",
        "../DealIn.Services/bin/Debug/net8.0/DealIn.Services.dll",
        "../Device.Services/bin/Debug/net8.0/Device.Services.dll",
        "../Deal.Services/bin/Debug/net8.0/Deal.Services.dll",
        "../User.Services/bin/Debug/net8.0/User.Services.dll",
        "../Admin.Services/bin/Debug/net8.0/Admin.Services.dll",
        "../Finance.Services/bin/Debug/net8.0/Finance.Services.dll",
        "../Messages/bin/Debug/net8.0/Messages.dll",
        "../Shared/bin/Debug/net8.0/Shared.dll",
        "../WebHost/bin/Debug/net8.0/WebHost.dll"
    ],
    "propertyNameConverters": [
        "../TypeGenHelpers/bin/Debug/net8.0/TypeGenHelpers.dll:TypeGenHelpers.TypeGenPropertyNameConverter"
    ],
    "typeNameConverters": [
        "../TypeGenHelpers/bin/Debug/net8.0/TypeGenHelpers.dll:TypeGenHelpers.TypeGenTypeNameConverter"
    ],
    "exportTypesAsInterfacesByDefault": true,
    "typeScriptFileExtension": "ts",
    "explicitPublicAccessor": true,
    "useTabCharacter": true,
    "outputPath": "../../frontend/src/helpers/client-models",
    "clearOutputDirectory": true,
    "customTypeMappings": {
        "System.Guid": "string",
        "System.TimeSpan": "string"
    },
    "typeUnionsForTypes": {
    }
}
@petero-dk
Copy link

I am pretty sure you could workaround this by making an intermediary type

Class ValidatorUserWalletValidator : Validator<UserWalletValidator> {}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants