RequiresUnreferencedCode & RequiresDynamicCode on anything using reflection

This commit is contained in:
7H3LaughingMan 2025-04-26 20:05:05 -05:00
parent ee7ba8bcfd
commit 7d2de9ad24
3 changed files with 35 additions and 0 deletions

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -104,6 +105,8 @@ public class CustomClassDefinition : HasPropertiesBase, ICustomTypeDefinition
/// <param name="type">The type of the class to create a custom class definition from.</param> /// <param name="type">The type of the class to create a custom class definition from.</param>
/// <returns>A new <see cref="CustomClassDefinition"/> instance.</returns> /// <returns>A new <see cref="CustomClassDefinition"/> instance.</returns>
/// <exception cref="ArgumentException">Thrown when the specified type is not a class.</exception> /// <exception cref="ArgumentException">Thrown when the specified type is not a class.</exception>
[RequiresUnreferencedCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
[RequiresDynamicCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
public static CustomClassDefinition FromClass(Type type) public static CustomClassDefinition FromClass(Type type)
{ {
ArgumentNullException.ThrowIfNull(type, nameof(type)); ArgumentNullException.ThrowIfNull(type, nameof(type));
@ -127,6 +130,8 @@ public class CustomClassDefinition : HasPropertiesBase, ICustomTypeDefinition
/// </summary> /// </summary>
/// <typeparam name="T">The type of the class to create a custom class definition from.</typeparam> /// <typeparam name="T">The type of the class to create a custom class definition from.</typeparam>
/// <returns>A new <see cref="CustomClassDefinition"/> instance.</returns> /// <returns>A new <see cref="CustomClassDefinition"/> instance.</returns>
[RequiresUnreferencedCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
[RequiresDynamicCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
public static CustomClassDefinition FromClass<T>() where T : class, new() => FromClass(() => new T()); public static CustomClassDefinition FromClass<T>() where T : class, new() => FromClass(() => new T());
/// <summary> /// <summary>
@ -135,6 +140,8 @@ public class CustomClassDefinition : HasPropertiesBase, ICustomTypeDefinition
/// <typeparam name="T">The type of the class to create a custom class definition from.</typeparam> /// <typeparam name="T">The type of the class to create a custom class definition from.</typeparam>
/// <param name="factory">The factory function that creates an instance of the class.</param> /// <param name="factory">The factory function that creates an instance of the class.</param>
/// <returns>A new <see cref="CustomClassDefinition"/> instance.</returns> /// <returns>A new <see cref="CustomClassDefinition"/> instance.</returns>
[RequiresUnreferencedCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
[RequiresDynamicCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
public static CustomClassDefinition FromClass<T>(Func<T> factory) where T : class public static CustomClassDefinition FromClass<T>(Func<T> factory) where T : class
{ {
var instance = factory(); var instance = factory();
@ -149,6 +156,8 @@ public class CustomClassDefinition : HasPropertiesBase, ICustomTypeDefinition
}; };
} }
[RequiresUnreferencedCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
[RequiresDynamicCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
private static IProperty ConvertPropertyInfoToIProperty(object instance, PropertyInfo propertyInfo) private static IProperty ConvertPropertyInfoToIProperty(object instance, PropertyInfo propertyInfo)
{ {
switch (propertyInfo.PropertyType) switch (propertyInfo.PropertyType)
@ -183,6 +192,8 @@ public class CustomClassDefinition : HasPropertiesBase, ICustomTypeDefinition
throw new NotSupportedException($"Type '{propertyInfo.PropertyType.Name}' is not supported in custom classes."); throw new NotSupportedException($"Type '{propertyInfo.PropertyType.Name}' is not supported in custom classes.");
} }
[RequiresUnreferencedCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
[RequiresDynamicCode("Use manually defined class properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#class-properties")]
private static List<IProperty> GetNestedProperties(Type type, object instance) private static List<IProperty> GetNestedProperties(Type type, object instance)
{ {
var defaultInstance = Activator.CreateInstance(type); var defaultInstance = Activator.CreateInstance(type);

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
namespace DotTiled; namespace DotTiled;
@ -53,6 +54,8 @@ public class CustomEnumDefinition : ICustomTypeDefinition
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="storageType">The storage type of the custom enum. Defaults to <see cref="CustomEnumStorageType.String"/> to be consistent with Tiled.</param> /// <param name="storageType">The storage type of the custom enum. Defaults to <see cref="CustomEnumStorageType.String"/> to be consistent with Tiled.</param>
/// <returns></returns> /// <returns></returns>
[RequiresUnreferencedCode("Use manually defined enum properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#enum-properties")]
[RequiresDynamicCode("Use manually defined enum properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#enum-properties")]
public static CustomEnumDefinition FromEnum<T>(CustomEnumStorageType storageType = CustomEnumStorageType.String) where T : Enum public static CustomEnumDefinition FromEnum<T>(CustomEnumStorageType storageType = CustomEnumStorageType.String) where T : Enum
{ {
var type = typeof(T); var type = typeof(T);
@ -73,6 +76,8 @@ public class CustomEnumDefinition : ICustomTypeDefinition
/// <param name="type">The enum type to create a custom enum definition from.</param> /// <param name="type">The enum type to create a custom enum definition from.</param>
/// <param name="storageType">The storage type of the custom enum. Defaults to <see cref="CustomEnumStorageType.String"/> to be consistent with Tiled.</param> /// <param name="storageType">The storage type of the custom enum. Defaults to <see cref="CustomEnumStorageType.String"/> to be consistent with Tiled.</param>
/// <returns></returns> /// <returns></returns>
[RequiresUnreferencedCode("Use manually defined enum properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#enum-properties")]
[RequiresDynamicCode("Use manually defined enum properties.", Url = "https://dcronqvist.github.io/DotTiled/docs/essentials/custom-properties.html#enum-properties")]
public static CustomEnumDefinition FromEnum(Type type, CustomEnumStorageType storageType = CustomEnumStorageType.String) public static CustomEnumDefinition FromEnum(Type type, CustomEnumStorageType storageType = CustomEnumStorageType.String)
{ {
if (!type.IsEnum) if (!type.IsEnum)

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
namespace DotTiled; namespace DotTiled;
@ -36,6 +37,7 @@ public interface IHasProperties
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns></returns> /// <returns></returns>
[RequiresUnreferencedCode("Use 'MapPropertiesTo' with a custom mapper instead.")]
T MapPropertiesTo<T>() where T : new(); T MapPropertiesTo<T>() where T : new();
/// <summary> /// <summary>
@ -44,7 +46,16 @@ public interface IHasProperties
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="initializer"></param> /// <param name="initializer"></param>
/// <returns></returns> /// <returns></returns>
[RequiresUnreferencedCode("Use 'MapPropertiesTo' with a custom mapper instead.")]
T MapPropertiesTo<T>(Func<T> initializer); T MapPropertiesTo<T>(Func<T> initializer);
/// <summary>
/// Maps all properties in this object to a new instance of the specified type using the provided mapper.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="mapper"></param>
/// <returns></returns>
T MapPropertiesTo<T>(Func<IList<IProperty>, T> mapper);
} }
/// <summary> /// <summary>
@ -85,11 +96,17 @@ public abstract class HasPropertiesBase : IHasProperties
} }
/// <inheritdoc/> /// <inheritdoc/>
[RequiresUnreferencedCode("Use 'MapPropertiesTo' with a custom mapper instead.")]
public T MapPropertiesTo<T>() where T : new() => CreateMappedInstance<T>(GetProperties()); public T MapPropertiesTo<T>() where T : new() => CreateMappedInstance<T>(GetProperties());
/// <inheritdoc/> /// <inheritdoc/>
[RequiresUnreferencedCode("Use 'MapPropertiesTo' with a custom mapper instead.")]
public T MapPropertiesTo<T>(Func<T> initializer) => CreateMappedInstance(GetProperties(), initializer); public T MapPropertiesTo<T>(Func<T> initializer) => CreateMappedInstance(GetProperties(), initializer);
/// <inheritdoc/>
public T MapPropertiesTo<T>(Func<IList<IProperty>, T> mapper) => mapper(GetProperties());
[RequiresUnreferencedCode("Use 'MapPropertiesTo' with a custom mapper instead.")]
private static object CreatedMappedInstance(object instance, IList<IProperty> properties) private static object CreatedMappedInstance(object instance, IList<IProperty> properties)
{ {
var type = instance.GetType(); var type = instance.GetType();
@ -141,8 +158,10 @@ public abstract class HasPropertiesBase : IHasProperties
return instance; return instance;
} }
[RequiresUnreferencedCode("Use 'MapPropertiesTo' with a custom mapper instead.")]
private static T CreateMappedInstance<T>(IList<IProperty> properties) where T : new() => private static T CreateMappedInstance<T>(IList<IProperty> properties) where T : new() =>
(T)CreatedMappedInstance(Activator.CreateInstance<T>() ?? throw new InvalidOperationException($"Failed to create instance of '{typeof(T).Name}'."), properties); (T)CreatedMappedInstance(Activator.CreateInstance<T>() ?? throw new InvalidOperationException($"Failed to create instance of '{typeof(T).Name}'."), properties);
[RequiresUnreferencedCode("Use 'MapPropertiesTo' with a custom mapper instead.")]
private static T CreateMappedInstance<T>(IList<IProperty> properties, Func<T> initializer) => (T)CreatedMappedInstance(initializer(), properties); private static T CreateMappedInstance<T>(IList<IProperty> properties, Func<T> initializer) => (T)CreatedMappedInstance(initializer(), properties);
} }