Skip to content

Make PdfSharpCore trimmable #293

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 5 commits into from
Aug 31, 2022
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
6 changes: 6 additions & 0 deletions PdfSharpCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfSharpCore.Test", "PdfSharpCore.Test\PdfSharpCore.Test.csproj", "{A862C0CE-C095-459C-A32B-8FCDD15A93BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp", "SampleApp\SampleApp.csproj", "{E2F17280-6C54-4711-AF1C-3286D2C45526}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -44,6 +46,10 @@ Global
{A862C0CE-C095-459C-A32B-8FCDD15A93BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A862C0CE-C095-459C-A32B-8FCDD15A93BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A862C0CE-C095-459C-A32B-8FCDD15A93BF}.Release|Any CPU.Build.0 = Release|Any CPU
{E2F17280-6C54-4711-AF1C-3286D2C45526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2F17280-6C54-4711-AF1C-3286D2C45526}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2F17280-6C54-4711-AF1C-3286D2C45526}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2F17280-6C54-4711-AF1C-3286D2C45526}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
103 changes: 103 additions & 0 deletions PdfSharpCore/!internal/DynamicallyAccessedMemberTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Included in .net 5 and later
#if !NET5_0_OR_GREATER
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// Specifies the types of members that are dynamically accessed.
///
/// This enumeration has a <see cref="FlagsAttribute"/> attribute that allows a
/// bitwise combination of its member values.
/// </summary>
[Flags]
#if SYSTEM_PRIVATE_CORELIB
public
#else
internal
#endif
enum DynamicallyAccessedMemberTypes
{
/// <summary>
/// Specifies no members.
/// </summary>
None = 0,

/// <summary>
/// Specifies the default, parameterless public constructor.
/// </summary>
PublicParameterlessConstructor = 0x0001,

/// <summary>
/// Specifies all public constructors.
/// </summary>
PublicConstructors = 0x0002 | PublicParameterlessConstructor,

/// <summary>
/// Specifies all non-public constructors.
/// </summary>
NonPublicConstructors = 0x0004,

/// <summary>
/// Specifies all public methods.
/// </summary>
PublicMethods = 0x0008,

/// <summary>
/// Specifies all non-public methods.
/// </summary>
NonPublicMethods = 0x0010,

/// <summary>
/// Specifies all public fields.
/// </summary>
PublicFields = 0x0020,

/// <summary>
/// Specifies all non-public fields.
/// </summary>
NonPublicFields = 0x0040,

/// <summary>
/// Specifies all public nested types.
/// </summary>
PublicNestedTypes = 0x0080,

/// <summary>
/// Specifies all non-public nested types.
/// </summary>
NonPublicNestedTypes = 0x0100,

/// <summary>
/// Specifies all public properties.
/// </summary>
PublicProperties = 0x0200,

/// <summary>
/// Specifies all non-public properties.
/// </summary>
NonPublicProperties = 0x0400,

/// <summary>
/// Specifies all public events.
/// </summary>
PublicEvents = 0x0800,

/// <summary>
/// Specifies all non-public events.
/// </summary>
NonPublicEvents = 0x1000,

/// <summary>
/// Specifies all interfaces implemented by the type.
/// </summary>
Interfaces = 0x2000,

/// <summary>
/// Specifies all members.
/// </summary>
All = ~None
}
}
#endif
59 changes: 59 additions & 0 deletions PdfSharpCore/!internal/DynamicallyAccessedMembersAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Included in .net 5 and later
#if !NET5_0_OR_GREATER
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// Indicates that certain members on a specified <see cref="Type"/> are accessed dynamically,
/// for example through <see cref="System.Reflection"/>.
/// </summary>
/// <remarks>
/// This allows tools to understand which members are being accessed during the execution
/// of a program.
///
/// This attribute is valid on members whose type is <see cref="Type"/> or <see cref="string"/>.
///
/// When this attribute is applied to a location of type <see cref="string"/>, the assumption is
/// that the string represents a fully qualified type name.
///
/// When this attribute is applied to a class, interface, or struct, the members specified
/// can be accessed dynamically on <see cref="Type"/> instances returned from calling
/// <see cref="object.GetType"/> on instances of that class, interface, or struct.
///
/// If the attribute is applied to a method it's treated as a special case and it implies
/// the attribute should be applied to the "this" parameter of the method. As such the attribute
/// should only be used on instance methods of types assignable to System.Type (or string, but no methods
/// will use it there).
/// </remarks>
[AttributeUsage(
AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter |
AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method |
AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct,
Inherited = false)]
#if SYSTEM_PRIVATE_CORELIB
public
#else
internal
#endif
sealed class DynamicallyAccessedMembersAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="DynamicallyAccessedMembersAttribute"/> class
/// with the specified member types.
/// </summary>
/// <param name="memberTypes">The types of members dynamically accessed.</param>
public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
{
MemberTypes = memberTypes;
}

/// <summary>
/// Gets the <see cref="DynamicallyAccessedMemberTypes"/> which specifies the type
/// of members dynamically accessed.
/// </summary>
public DynamicallyAccessedMemberTypes MemberTypes { get; }
}
}
#endif
10 changes: 8 additions & 2 deletions PdfSharpCore/Pdf/EntryInfoAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#endregion

using System;
using System.Diagnostics.CodeAnalysis;

namespace PdfSharpCore.Pdf
{
Expand Down Expand Up @@ -90,14 +91,16 @@ public KeyInfoAttribute(string version, KeyType keyType)
KeyType = keyType;
}

public KeyInfoAttribute(KeyType keyType, Type objectType)
public KeyInfoAttribute(KeyType keyType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
Type objectType)
{
//_version = version;
KeyType = keyType;
_objectType = objectType;
}

public KeyInfoAttribute(string version, KeyType keyType, Type objectType)
public KeyInfoAttribute(string version, KeyType keyType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
Type objectType)
{
//_version = version;
KeyType = keyType;
Expand All @@ -118,11 +121,14 @@ public KeyType KeyType
}
KeyType _entryType;

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public Type ObjectType
{
get { return _objectType; }
set { _objectType = value; }
}

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
Type _objectType;

public string FixedValue
Expand Down
3 changes: 2 additions & 1 deletion PdfSharpCore/Pdf/KeysBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#endregion

using System;
using System.Diagnostics.CodeAnalysis;

namespace PdfSharpCore.Pdf
{
Expand All @@ -36,7 +37,7 @@ namespace PdfSharpCore.Pdf
/// </summary>
public class KeysBase
{
internal static DictionaryMeta CreateMeta(Type type)
internal static DictionaryMeta CreateMeta([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] Type type)
{
return new DictionaryMeta(type);
}
Expand Down
22 changes: 21 additions & 1 deletion PdfSharpCore/Pdf/KeysMeta.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
using System.Diagnostics;
using System.Collections.Generic;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;

namespace PdfSharpCore.Pdf
{
Expand Down Expand Up @@ -85,11 +86,13 @@ public string FixedValue
}
readonly string _fixedValue;

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public Type ObjectType
{
get { return _objectType; }
set { _objectType = value; }
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
Type _objectType;

public bool CanBeIndirect
Expand All @@ -100,6 +103,7 @@ public bool CanBeIndirect
/// <summary>
/// Returns the type of the object to be created as value for the described key.
/// </summary>
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public Type GetValueType()
{
Type type = _objectType;
Expand Down Expand Up @@ -180,8 +184,21 @@ public Type GetValueType()
/// </summary>
internal class DictionaryMeta
{
public DictionaryMeta(Type type)
public DictionaryMeta([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] Type type)
{
#if NET5_0_OR_GREATER
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
foreach (FieldInfo field in fields)
{
var attributes = field.GetCustomAttributes<KeyInfoAttribute>(false);
foreach (var attribute in attributes)
{
KeyDescriptor descriptor = new KeyDescriptor(attribute);
descriptor.KeyValue = (string)field.GetValue(null);
_keyDescriptors[descriptor.KeyValue] = descriptor;
}
}
#else
// Rewritten for WinRT.
CollectKeyDescriptors(type);
//var fields = type.GetRuntimeFields(); // does not work
Expand All @@ -196,8 +213,10 @@ public DictionaryMeta(Type type)
// _keyDescriptors[descriptor.KeyValue] = descriptor;
// }
//}
#endif
}

#if !NET5_0_OR_GREATER
// Background: The function GetRuntimeFields gets constant fields only for the specified type,
// not for its base types. So we have to walk recursively through base classes.
// The docmentation says full trust for the immediate caller is required for property BaseClass.
Expand All @@ -220,6 +239,7 @@ void CollectKeyDescriptors(Type type)
if (type != typeof(object) && type != typeof(PdfObject))
CollectKeyDescriptors(type);
}
#endif

/// <summary>
/// Gets the KeyDescriptor of the specified key, or null if no such descriptor exits.
Expand Down
9 changes: 6 additions & 3 deletions PdfSharpCore/Pdf/PdfDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
using PdfSharpCore.Pdf.Filters;
using PdfSharpCore.Pdf.Advanced;
using PdfSharpCore.Pdf.Internal;
using System.Diagnostics.CodeAnalysis;

namespace PdfSharpCore.Pdf
{
Expand Down Expand Up @@ -935,6 +936,7 @@ public PdfItem GetValue(string key)
/// <summary>
/// Returns the type of the object to be created as value of the specified key.
/// </summary>
[return:DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
Type GetValueType(string key) // TODO: move to PdfObject
{
Type type = null;
Expand All @@ -952,7 +954,7 @@ Type GetValueType(string key) // TODO: move to PdfObject
return type;
}

PdfArray CreateArray(Type type, PdfArray oldArray)
PdfArray CreateArray([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]Type type, PdfArray oldArray)
{
// Rewritten WinRT style.
PdfArray array = null;
Expand Down Expand Up @@ -991,7 +993,8 @@ PdfArray CreateArray(Type type, PdfArray oldArray)
return array;
}

PdfDictionary CreateDictionary(Type type, PdfDictionary oldDictionary)
PdfDictionary CreateDictionary([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
Type type, PdfDictionary oldDictionary)
{
// Rewritten WinRT style.
PdfDictionary dict = null;
Expand Down Expand Up @@ -1028,7 +1031,7 @@ PdfDictionary CreateDictionary(Type type, PdfDictionary oldDictionary)
return dict;
}

PdfItem CreateValue(Type type, PdfDictionary oldValue)
PdfItem CreateValue([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]Type type, PdfDictionary oldValue)
{

// Rewritten WinRT style.
Expand Down
4 changes: 3 additions & 1 deletion PdfSharpCore/PdfSharpCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ PdfSharpCore is a partial port of PdfSharp.Xamarin for .NET Core Additionally Mi
<RepositoryUrl>https://github.com/ststeiger/PdfSharpCore</RepositoryUrl>
<PackageReleaseNotes>PdfSharpCore is a partial port of PdfSharp.Xamarin for .NET Core Additionally MigraDoc has been ported as well (from version 1.32)</PackageReleaseNotes>
<PackageTags>NuggetV1.0.0 (8ea343d5898342a563b9d4df2d67e27aaea9ac01)</PackageTags>
<summary>PdfSharp for .NET Core</summary>
<summary>PdfSharp for .NET Core</summary>
<IsTrimmable>true</IsTrimmable>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
Expand Down
Loading