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

PersistedAssemblyBuilder, types throw exceptions even after created #108733

Closed
snakex64 opened this issue Oct 9, 2024 · 7 comments
Closed

PersistedAssemblyBuilder, types throw exceptions even after created #108733

snakex64 opened this issue Oct 9, 2024 · 7 comments
Labels
area-System.Reflection.Emit help wanted [up-for-grabs] Good issue for external contributors
Milestone

Comments

@snakex64
Copy link
Contributor

snakex64 commented Oct 9, 2024

Description

Hi! I have been trying the new PersistedAssemblyBuilder in .net 9. I have been using the previous AssemblyBuilder.DefineDynamicAssembly to create assemblies at runtime but it seems like the new one might be missing some features.

I use ExpressionTree to create the method's body, and then compile those expression tree directly in the ILGenerator of that method. I had issues in the past where I couldn't get information about properties and methods out of the type until I call TypeBuilder.CreateType() on it, then everything works fine, such as type.GetProperties() or type.GetProperty(name)

It seems now that even if I call CreateType() on the type builder, I still can't call most of the usual reflection methods such as GetProperties()
Is there a way around this?

To make it work in the past, I ended up creating internal static classes that contain the actual implementation. That allowed me to have one class that had "empty methods", basically generating the IL code to do something like:

public int MyMethod(int a, int b)
{
    return MyInternalStaticClass.MyMethod(this, a, b);
}

That way I could call CreateType() on that type before I actually know what to put inside the method itself, since I sadly can't do that before the type is created.
It seems now that my fix might not be enough anymore.

Reproduction Steps

In .NET 9 RC1 Use the PersistedAssemblyBuilder to create a class, create the type and call GetProperties() on created "Type"

Expected behavior

I would expect the "Type" object to behave normally and provide all necessary information normally

Actual behavior

A lot of methods are clearly just throwing exceptions and don't have implementations at all. Such as "GetInterfaces()" has an implementation but "GetInterface" doesn't, even though they both ping back on the same backend object.

Image

Regression?

It used to work with the previous AssemblyBuilder.DefineDynamicAssembly but since we can't use it anymore to save dynamic assemblies I don't have a choice but to use the new PersistedAssemblyBuilder

Known Workarounds

No response

Configuration

.NET 9 RC1

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Oct 9, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Oct 9, 2024
@vcsjones vcsjones added area-System.Reflection.Emit and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Oct 9, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-reflection-emit
See info in area-owners.md if you want to be subscribed.

@buyaa-n
Copy link
Contributor

buyaa-n commented Oct 10, 2024

A lot of methods are clearly just throwing exceptions and don't have implementations at all. Such as "GetInterfaces()" has an implementation but "GetInterface" doesn't, even though they both ping back on the same backend object.

Yes, we tried to implement as much as we can, but there are still lot of methods that are not implemented, some of them even could not be implemented. But the methods you are requesting are can be implemented.

@snakex64 If you like you could also contribute and implement those methods. This should be quite similar to the GetFields(BindingFlags) API you showed in the picture plus adding unit tests

@buyaa-n buyaa-n added this to the 10.0.0 milestone Oct 10, 2024
@buyaa-n buyaa-n added help wanted [up-for-grabs] Good issue for external contributors and removed untriaged New issue has not been triaged by the area owner labels Oct 10, 2024
@snakex64
Copy link
Contributor Author

@snakex64 If you like you could also contribute and implement those methods. This should be quite similar to the GetFields(BindingFlags) API you showed in the picture plus adding unit tests

I sure can try. Can you point me towards where to add the tests ? I had a quick look yesterday but I'm not sure.

Adding the code is the easy part, I'll try to get a setup working

@buyaa-n
Copy link
Contributor

buyaa-n commented Oct 10, 2024

Great, thank you!

type.GetProperties() or type.GetProperty(name) tests can be added to AssemblySavePropertyBuilderTests

If you add GetInterface(...) implementation test could be added to AssemblySaveTypeBuilderAPIsTests

Here is instructions how to build and run tests Running tests for a single library

@snakex64
Copy link
Contributor Author

snakex64 commented Oct 28, 2024

@buyaa-n I added a PR. Really not sure about the GetProperty as it was a bit more complicated to do, hopefully it's at least a good starting point.

@snakex64
Copy link
Contributor Author

snakex64 commented Dec 5, 2024

Closed by #109320

@snakex64 snakex64 closed this as completed Dec 5, 2024
@kasperk81
Copy link
Contributor

@snakex64

public override string? AssemblyQualifiedName => throw new NotSupportedException();
public override string? FullName => _strFullName ??= TypeNameBuilder.ToString(this, TypeNameBuilder.Format.FullName);

can AssemblyQualifiedName use TypeNameBuilder.ToString with qualified name format
internal static string? ToString(Type type, Format format)

public override string? AssemblyQualifiedName => _strAssemblyQualifiedName ??= TypeNameBuilder.ToString(this, TypeNameBuilder.Format.AssemblyQualifiedName);

@github-actions github-actions bot locked and limited conversation to collaborators Jan 14, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Reflection.Emit help wanted [up-for-grabs] Good issue for external contributors
Projects
None yet
Development

No branches or pull requests

4 participants