-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
[API Proposal]: Generic Activator API to create a type from a possibly non-public parameterless constructor #85541
Comments
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsBackground and motivationTo construct a object of type For our CoreCLR accelerates both NativeAOT has a very powerful optimization path for cc: @dotnet/ilc-contrib API Proposalnamespace System;
public static class Activator
{
+ public void CreateInstance<T>(bool nonPublic);
} API UsageT instance = Activator.CreateInstance<T>(nonPublic: true); Alternative DesignsWe can just have this method as We could also introduce a custom intrinsic in NativeAOT's CoreLib that the RisksNo response
|
Marked blocking as this is blocking merging in #85419 |
Why can't we tell people to fix their safe handles first if they want to use source generators? |
We can choose to take that breaking change if we want to, but we considered that a large breaking change and didn't want to take it. |
If taking the breaking change is preferable to providing a NativeAOT-intrinsic API here, we can do the breaking change instead. |
We can implement the exact same optimization for native AOT as well. We do not need a new API just to compensate for a missing optimization on native AOT. I think depending on private reflection in modern marshallers is sub-optimal. I think we should make SafeHandleMarshaller to have |
If we can implement it with the existing API surface, I'd happily support that.
We can't make it have the I've just built the runtime with the smaller breaking change (requiring a public constructor for |
I have confirmed that only allowing public constructors removes the reflection stack. I'll update the SafeHandle PR to include the breaking change. |
Background and motivation
To construct a object of type
T
from a parameterless constructor, we have a few API options today. If we know that the constructor is public, we can useActivator.CreateInstance<T>()
andActivator.CreateInstance(Type)
. If the constructor may be non-public, we only have a non-genericActivator.CreateInstance(Type, bool)
method.For our
SafeHandleMarshaller
type that we use in the interop source generators, we need to support non-public constructors for backward-compatibility reasons. As a result, we need to useActivator.CreateInstance(Type, bool)
to optionally support a non-public default constructor.CoreCLR accelerates both
Activator.CreateInstance<T>()
andActivator.CreateInstance(Type, bool)
to be almost as fast as writingnew T()
with a specificT
, so adding a new genericActivator.CreateInstance
method to support constructing an object from a non-public constructor isn't necessary.NativeAOT has a very powerful optimization path for
Activator.CreateInstance<T>()
to avoid pulling in the reflection stack. It does not have this optimization forActivator.CreateInstance(Type, bool)
, and it cannot have this optimization in a non-generic context. As a result, the newSafeHandleMarshaller
type roots the reflection stack, increasing the size of any apps that use it by quite a bit. SinceLibraryImport
s withSafeHandle
s are used in the code for basically every application type (Web, Console, UI), we end up always rooting the reflection stack. If we add this API, we can implement an intrinsic implementation on NativeAOT that does not root the reflection stack and avoids the size regression.cc: @dotnet/ilc-contrib
API Proposal
namespace System; public static class Activator { + public void CreateInstance<T>(bool nonPublic); }
API Usage
Alternative Designs
We can just have this method as
internal
in System.Private.CoreLib to avoid expanding the public API surface ofActivator
, as the SafeHandleMarshaller type will live in CoreLib.We could also introduce a custom intrinsic in NativeAOT's CoreLib that the
SafeHandleMarshaller
could use on NativeAOT.Risks
No response
The text was updated successfully, but these errors were encountered: