Skip to content

Implement DAMT.*WithInherited #109608

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

Merged
merged 4 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ public static IEnumerable<TypeSystemEntity> GetDynamicallyAccessedMembers(this T

if (memberTypes.HasFlag(DynamicallyAccessedMemberTypes.NonPublicConstructors))
{
foreach (var c in typeDefinition.GetConstructorsOnType(filter: null, bindingFlags: BindingFlags.NonPublic))
bool withInherited = !declaredOnly && memberTypes.HasFlag(DynamicallyAccessedMemberTypesEx.NonPublicConstructorsWithInherited);
foreach (var c in typeDefinition.ApplyIncludeInherited(t => t.GetConstructorsOnType(filter: null, bindingFlags: BindingFlags.NonPublic), withInherited))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we can't make GetConstructorsOnType (and similar) walk up the base types, based on the binding flags passed in? (Is it just that we're trying to keep GetConstructorsOnType aligned with the reflection semantics?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent a good part of the day trying to figure out how to do this :)

The problem is that all of these APIs take BindingFlags, which is a public enum with documented meaning of all the flags. So:

  • Private means: do not recurse in bases.
  • DeclaredOnly also has a meaning for publics (it means do not recurse for publics)

I had an extra bool that says "please recurse into bases", but the extra argument then conflicts with the default reflection semantics and with whatever BindingFlags specify. This didn't feel particularly readable.

Then I considered just not using BindingFlags here, but we do read random BindingFlags using dataflow and just send them over to here so we need some translation to exist. We also sometimes inject DeclaredOnly by ourselves.

All in all what I have here felt like the cleanest because WithInherited behavior handling can be restricted to this one method instead of complicating the surface area everywhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks for the explanation!

yield return c;
}

if (memberTypes.HasFlag(DynamicallyAccessedMemberTypes.PublicConstructors))
{
foreach (var c in typeDefinition.GetConstructorsOnType(filter: null, bindingFlags: BindingFlags.Public))
bool withInherited = !declaredOnly && memberTypes.HasFlag(DynamicallyAccessedMemberTypesEx.PublicConstructorsWithInherited);
foreach (var c in typeDefinition.ApplyIncludeInherited(t => t.GetConstructorsOnType(filter: null, bindingFlags: BindingFlags.Public), withInherited))
yield return c;
}

Expand All @@ -52,7 +54,8 @@ public static IEnumerable<TypeSystemEntity> GetDynamicallyAccessedMembers(this T

if (memberTypes.HasFlag(DynamicallyAccessedMemberTypes.NonPublicMethods))
{
foreach (var m in typeDefinition.GetMethodsOnTypeHierarchy(filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags))
bool withInherited = !declaredOnly && memberTypes.HasFlag(DynamicallyAccessedMemberTypesEx.NonPublicMethodsWithInherited);
foreach (var m in typeDefinition.ApplyIncludeInherited(t => t.GetMethodsOnTypeHierarchy(filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags), withInherited))
yield return m;
}

Expand All @@ -64,7 +67,8 @@ public static IEnumerable<TypeSystemEntity> GetDynamicallyAccessedMembers(this T

if (memberTypes.HasFlag(DynamicallyAccessedMemberTypes.NonPublicFields))
{
foreach (var f in typeDefinition.GetFieldsOnTypeHierarchy(filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags))
bool withInherited = !declaredOnly && memberTypes.HasFlag(DynamicallyAccessedMemberTypesEx.NonPublicFieldsWithInherited);
foreach (var f in typeDefinition.ApplyIncludeInherited(t => t.GetFieldsOnTypeHierarchy(filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags), withInherited))
yield return f;
}

Expand All @@ -76,7 +80,8 @@ public static IEnumerable<TypeSystemEntity> GetDynamicallyAccessedMembers(this T

if (memberTypes.HasFlag(DynamicallyAccessedMemberTypes.NonPublicNestedTypes))
{
foreach (var t in typeDefinition.GetNestedTypesOnType(filter: null, bindingFlags: BindingFlags.NonPublic))
bool withInherited = !declaredOnly && memberTypes.HasFlag(DynamicallyAccessedMemberTypesEx.NonPublicNestedTypesWithInherited);
foreach (var t in typeDefinition.ApplyIncludeInherited(t => t.GetNestedTypesOnType(filter: null, bindingFlags: BindingFlags.NonPublic), withInherited))
{
yield return t;
var members = new List<TypeSystemEntity>();
Expand All @@ -88,7 +93,8 @@ public static IEnumerable<TypeSystemEntity> GetDynamicallyAccessedMembers(this T

if (memberTypes.HasFlag(DynamicallyAccessedMemberTypes.PublicNestedTypes))
{
foreach (var t in typeDefinition.GetNestedTypesOnType(filter: null, bindingFlags: BindingFlags.Public))
bool withInherited = !declaredOnly && memberTypes.HasFlag(DynamicallyAccessedMemberTypesEx.PublicNestedTypesWithInherited);
foreach (var t in typeDefinition.ApplyIncludeInherited(t => t.GetNestedTypesOnType(filter: null, bindingFlags: BindingFlags.Public), withInherited))
{
yield return t;
var members = new List<TypeSystemEntity>();
Expand All @@ -100,7 +106,8 @@ public static IEnumerable<TypeSystemEntity> GetDynamicallyAccessedMembers(this T

if (memberTypes.HasFlag(DynamicallyAccessedMemberTypes.NonPublicProperties))
{
foreach (var p in typeDefinition.GetPropertiesOnTypeHierarchy(filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags))
bool withInherited = !declaredOnly && memberTypes.HasFlag(DynamicallyAccessedMemberTypesEx.NonPublicPropertiesWithInherited);
foreach (var p in typeDefinition.ApplyIncludeInherited(t => t.GetPropertiesOnTypeHierarchy(filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags), withInherited))
yield return p;
}

Expand All @@ -112,7 +119,8 @@ public static IEnumerable<TypeSystemEntity> GetDynamicallyAccessedMembers(this T

if (memberTypes.HasFlag(DynamicallyAccessedMemberTypes.NonPublicEvents))
{
foreach (var e in typeDefinition.GetEventsOnTypeHierarchy(filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags))
bool withInherited = !declaredOnly && memberTypes.HasFlag(DynamicallyAccessedMemberTypesEx.NonPublicEventsWithInherited);
foreach (var e in typeDefinition.ApplyIncludeInherited(t => t.GetEventsOnTypeHierarchy(filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags), withInherited))
yield return e;
}

Expand Down Expand Up @@ -504,6 +512,20 @@ private static DefType TryGetBaseType(this TypeDesc type)
}
}

private static IEnumerable<T> ApplyIncludeInherited<T>(this TypeDesc type, Func<TypeDesc, IEnumerable<T>> selector, bool includeBases)
{
do
{
foreach (var m in selector(type))
yield return m;

if (!includeBases)
yield break;

type = type.TryGetBaseType();
} while (type != null);
}

private static DefType[] TryGetExplicitlyImplementedInterfaces(this TypeDesc type)
{
if (type is MetadataType mdType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
<Compile Include="..\..\Common\TypeSystem\Interop\UnmanagedCallingConventions.cs" Link="Interop\UnmanagedCallingConventions.cs" />
<Compile Include="..\ILCompiler.Reflection.ReadyToRun\PEReaderExtensions.cs" Link="Reflection\PEReaderExtensions.cs" />
<Compile Include="$(ToolsProjectRoot)illink\src\ILLink.Shared\ClosedAttribute.cs" Link="ILLink.Shared\ClosedAttribute.cs" />
<Compile Include="$(ToolsProjectRoot)illink\src\ILLink.Shared\DynamicallyAccessedMemberTypesEx.cs" Link="ILLink.Shared\DynamicallyAccessedMemberTypesEx.cs" />
<Compile Include="$(ToolsProjectRoot)illink\src\ILLink.Shared\ParameterIndex.cs" Link="ILLink.Shared\ParameterIndex.cs" />
<Compile Include="$(ToolsProjectRoot)illink\src\ILLink.Shared\TrimAnalysis\ReferenceKind.cs" Link="ILLink.Shared\TrimAnalysis\ReferenceKind.cs" />
<Compile Include="$(ToolsProjectRoot)illink\src\ILLink.Shared\TypeSystemProxy\GenericParameterProxy.cs" Link="ILLink.Shared\TypeSystemProxy\GenericParameterProxy.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,76 @@ enum DynamicallyAccessedMemberTypes
/// </summary>
Interfaces = 0x2000,

/// <summary>
/// Specifies all non-public constructors, including those inherited from base classes.
/// </summary>
NonPublicConstructorsWithInherited = NonPublicConstructors | 0x4000,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't seen any discussion on the actual numerical values used here.
Why don't we add a "flag" which indicates "inherited"? Is it because there would be possible values which don't have any semantic meaning?
Alternatively we would not need to declare the flag, just use numeric values which effectively use the flag. In reality here we're introducing a new flag-like numeric value for each kind of metadata, which doesn't seem necessary. It consumes lot of available bits in this enum.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was discussed here: https://www.youtube.com/watch?v=uyXehmcAkHc&t=0h9m31s.

We want a bit for each of these because e.g. if I want a combination of non-public fields (including inherited) and public constructors (but not inherited), this shouldn't mean to inherit all constructors. So we need an extra bit for each "inherited" possibility.

We also set the existing bit just for convenience so that bit operations still work nicely (i.e. it would be sufficient to do NonPublicConstructorsWithInherited = 0x4000, but NonPublicConstructorsWithInherited = NonPublicConstructors | 0x4000 makes working with the enums easier because there's still the subset relationship and we can bit test without special casing.

The original proposal had two bits less (just "inherit constructors" and "inherit nested types") but the API review extended it to the more granular "inherit public constructors" and "inherit private constructors". Solely because the problem with .All is that it's too broad and we could have the same problem with "inherit constructors" being too broad in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot - makes sense.
Nit: Would be good to write this down somewhere in the issue or this PR - I have to admit I didn't watch the video.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the explanation to the PR description so that it's at the top.


/// <summary>
/// Specifies all non-public methods, including those inherited from base classes.
/// </summary>
NonPublicMethodsWithInherited = NonPublicMethods | 0x8000,

/// <summary>
/// Specifies all non-public fields, including those inherited from base classes.
/// </summary>
NonPublicFieldsWithInherited = NonPublicFields | 0x10000,

/// <summary>
/// Specifies all non-public nested types, including those inherited from base classes.
/// </summary>
NonPublicNestedTypesWithInherited = NonPublicNestedTypes | 0x20000,

/// <summary>
/// Specifies all non-public properties, including those inherited from base classes.
/// </summary>
NonPublicPropertiesWithInherited = NonPublicProperties | 0x40000,

/// <summary>
/// Specifies all non-public events, including those inherited from base classes.
/// </summary>
NonPublicEventsWithInherited = NonPublicEvents | 0x80000,

/// <summary>
/// Specifies all public constructors, including those inherited from base classes.
/// </summary>
PublicConstructorsWithInherited = PublicConstructors | 0x100000,

/// <summary>
/// Specifies all public nested types, including those inherited from base classes.
/// </summary>
PublicNestedTypesWithInherited = PublicNestedTypes | 0x200000,

/// <summary>
/// Specifies all constructors, including those inherited from base classes.
/// </summary>
AllConstructors = PublicConstructorsWithInherited | NonPublicConstructorsWithInherited,

/// <summary>
/// Specifies all methods, including those inherited from base classes.
/// </summary>
AllMethods = PublicMethods | NonPublicMethodsWithInherited,

/// <summary>
/// Specifies all fields, including those inherited from base classes.
/// </summary>
AllFields = PublicFields | NonPublicFieldsWithInherited,

/// <summary>
/// Specifies all nested types, including those inherited from base classes.
/// </summary>
AllNestedTypes = PublicNestedTypesWithInherited | NonPublicNestedTypesWithInherited,

/// <summary>
/// Specifies all properties, including those inherited from base classes.
/// </summary>
AllProperties = PublicProperties | NonPublicPropertiesWithInherited,

/// <summary>
/// Specifies all events, including those inherited from base classes.
/// </summary>
AllEvents = PublicEvents | NonPublicEventsWithInherited,

/// <summary>
/// Specifies all members.
/// </summary>
Expand Down
14 changes: 14 additions & 0 deletions src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8842,6 +8842,20 @@ public enum DynamicallyAccessedMemberTypes
PublicEvents = 2048,
NonPublicEvents = 4096,
Interfaces = 8192,
NonPublicConstructorsWithInherited = 16388,
NonPublicMethodsWithInherited = 32784,
AllMethods = 32792,
NonPublicFieldsWithInherited = 65600,
AllFields = 65632,
NonPublicNestedTypesWithInherited = 131328,
NonPublicPropertiesWithInherited = 263168,
AllProperties = 263680,
NonPublicEventsWithInherited = 528384,
AllEvents = 530432,
PublicConstructorsWithInherited = 1048579,
AllConstructors = 1064967,
PublicNestedTypesWithInherited = 2097280,
AllNestedTypes = 2228608,
}
[System.AttributeUsageAttribute(System.AttributeTargets.Constructor | System.AttributeTargets.Field | System.AttributeTargets.Method, AllowMultiple=true, Inherited=false)]
public sealed partial class DynamicDependencyAttribute : System.Attribute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ public static IEnumerable<ISymbol> GetDynamicallyAccessedMembers (this ITypeSymb
var declaredOnlyFlags = declaredOnly ? BindingFlags.DeclaredOnly : BindingFlags.Default;

if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicConstructors)) {
foreach (var c in typeDefinition.GetConstructorsOnType (filter: null, bindingFlags: BindingFlags.NonPublic))
bool withInherited = !declaredOnly && memberTypes.HasFlag (DynamicallyAccessedMemberTypesEx.NonPublicConstructorsWithInherited);
foreach (var c in typeDefinition.ApplyIncludeInherited (t => t.GetConstructorsOnType (filter: null, bindingFlags: BindingFlags.NonPublic), withInherited))
yield return c;
}

if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicConstructors)) {
foreach (var c in typeDefinition.GetConstructorsOnType (filter: null, bindingFlags: BindingFlags.Public))
bool withInherited = !declaredOnly && memberTypes.HasFlag (DynamicallyAccessedMemberTypesEx.PublicConstructorsWithInherited);
foreach (var c in typeDefinition.ApplyIncludeInherited (t => t.GetConstructorsOnType (filter: null, bindingFlags: BindingFlags.Public), withInherited))
yield return c;
}

Expand All @@ -45,7 +47,8 @@ public static IEnumerable<ISymbol> GetDynamicallyAccessedMembers (this ITypeSymb
}

if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicMethods)) {
foreach (var m in typeDefinition.GetMethodsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags))
bool withInherited = !declaredOnly && memberTypes.HasFlag (DynamicallyAccessedMemberTypesEx.NonPublicMethodsWithInherited);
foreach (var m in typeDefinition.ApplyIncludeInherited (t => t.GetMethodsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags), withInherited))
yield return m;
}

Expand All @@ -55,7 +58,8 @@ public static IEnumerable<ISymbol> GetDynamicallyAccessedMembers (this ITypeSymb
}

if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicFields)) {
foreach (var f in typeDefinition.GetFieldsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags))
bool withInherited = !declaredOnly && memberTypes.HasFlag (DynamicallyAccessedMemberTypesEx.NonPublicFieldsWithInherited);
foreach (var f in typeDefinition.ApplyIncludeInherited (t => t.GetFieldsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags), withInherited))
yield return f;
}

Expand All @@ -65,7 +69,8 @@ public static IEnumerable<ISymbol> GetDynamicallyAccessedMembers (this ITypeSymb
}

if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)) {
foreach (var nested in typeDefinition.GetNestedTypesOnType (filter: null, bindingFlags: BindingFlags.NonPublic)) {
bool withInherited = !declaredOnly && memberTypes.HasFlag (DynamicallyAccessedMemberTypesEx.NonPublicNestedTypesWithInherited);
foreach (var nested in typeDefinition.ApplyIncludeInherited (t => t.GetNestedTypesOnType (filter: null, bindingFlags: BindingFlags.NonPublic), withInherited)) {
yield return nested;
var members = new List<ISymbol> ();
nested.GetAllOnType (declaredOnly: false, members);
Expand All @@ -75,7 +80,8 @@ public static IEnumerable<ISymbol> GetDynamicallyAccessedMembers (this ITypeSymb
}

if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicNestedTypes)) {
foreach (var nested in typeDefinition.GetNestedTypesOnType (filter: null, bindingFlags: BindingFlags.Public)) {
bool withInherited = !declaredOnly && memberTypes.HasFlag (DynamicallyAccessedMemberTypesEx.PublicNestedTypesWithInherited);
foreach (var nested in typeDefinition.ApplyIncludeInherited (t => t.GetNestedTypesOnType (filter: null, bindingFlags: BindingFlags.Public), withInherited)) {
yield return nested;
var members = new List<ISymbol> ();
nested.GetAllOnType (declaredOnly: false, members);
Expand All @@ -85,7 +91,8 @@ public static IEnumerable<ISymbol> GetDynamicallyAccessedMembers (this ITypeSymb
}

if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicProperties)) {
foreach (var p in typeDefinition.GetPropertiesOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags))
bool withInherited = !declaredOnly && memberTypes.HasFlag (DynamicallyAccessedMemberTypesEx.NonPublicPropertiesWithInherited);
foreach (var p in typeDefinition.ApplyIncludeInherited (t => t.GetPropertiesOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags), withInherited))
yield return p;
}

Expand All @@ -95,7 +102,8 @@ public static IEnumerable<ISymbol> GetDynamicallyAccessedMembers (this ITypeSymb
}

if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicEvents)) {
foreach (var e in typeDefinition.GetEventsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags))
bool withInherited = !declaredOnly && memberTypes.HasFlag (DynamicallyAccessedMemberTypesEx.NonPublicEventsWithInherited);
foreach (var e in typeDefinition.ApplyIncludeInherited (t => t.GetEventsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic | declaredOnlyFlags), withInherited))
yield return e;
}

Expand Down Expand Up @@ -410,5 +418,18 @@ static void GetAllOnType (ITypeSymbol type, bool declaredOnly, List<ISymbol> mem
}
}
}
private static IEnumerable<T> ApplyIncludeInherited<T> (this ITypeSymbol thisType, Func<ITypeSymbol, IEnumerable<T>> selector, bool includeBases)
{
ITypeSymbol? type = thisType;
do {
foreach (var m in selector (type))
yield return m;

if (!includeBases)
yield break;

type = type.BaseType;
} while (type != null);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

namespace System.Diagnostics.CodeAnalysis
{
public static class DynamicallyAccessedMemberTypesEx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious why we need to add this? Is it that we don't have live flow of bits between the libraries and the trimmer code base here? If that is the case, migh be worth adding a comment so that eventually we delete this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ILLink is needed to build the framework so we can't build it with the live framework.

{
/// <summary>
/// Specifies all non-public constructors, including those inherited from base classes.
/// </summary>
public const DynamicallyAccessedMemberTypes NonPublicConstructorsWithInherited = DynamicallyAccessedMemberTypes.NonPublicConstructors | (DynamicallyAccessedMemberTypes) 0x4000;

/// <summary>
/// Specifies all non-public methods, including those inherited from base classes.
/// </summary>
public const DynamicallyAccessedMemberTypes NonPublicMethodsWithInherited = DynamicallyAccessedMemberTypes.NonPublicMethods | (DynamicallyAccessedMemberTypes) 0x8000;

/// <summary>
/// Specifies all non-public fields, including those inherited from base classes.
/// </summary>
public const DynamicallyAccessedMemberTypes NonPublicFieldsWithInherited = DynamicallyAccessedMemberTypes.NonPublicFields | (DynamicallyAccessedMemberTypes) 0x10000;

/// <summary>
/// Specifies all non-public nested types, including those inherited from base classes.
/// </summary>
public const DynamicallyAccessedMemberTypes NonPublicNestedTypesWithInherited = DynamicallyAccessedMemberTypes.NonPublicNestedTypes | (DynamicallyAccessedMemberTypes) 0x20000;

/// <summary>
/// Specifies all non-public properties, including those inherited from base classes.
/// </summary>
public const DynamicallyAccessedMemberTypes NonPublicPropertiesWithInherited = DynamicallyAccessedMemberTypes.NonPublicProperties | (DynamicallyAccessedMemberTypes) 0x40000;

/// <summary>
/// Specifies all non-public events, including those inherited from base classes.
/// </summary>
public const DynamicallyAccessedMemberTypes NonPublicEventsWithInherited = DynamicallyAccessedMemberTypes.NonPublicEvents | (DynamicallyAccessedMemberTypes) 0x80000;

/// <summary>
/// Specifies all public constructors, including those inherited from base classes.
/// </summary>
public const DynamicallyAccessedMemberTypes PublicConstructorsWithInherited = DynamicallyAccessedMemberTypes.PublicConstructors | (DynamicallyAccessedMemberTypes) 0x100000;

/// <summary>
/// Specifies all public nested types, including those inherited from base classes.
/// </summary>
public const DynamicallyAccessedMemberTypes PublicNestedTypesWithInherited = DynamicallyAccessedMemberTypes.PublicNestedTypes | (DynamicallyAccessedMemberTypes) 0x200000;
}
}
Loading
Loading