Skip to content
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 @@ -14,7 +14,7 @@
<PropertyGroup>
<IsPackable>true</IsPackable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TargetFrameworks>netstandard2.0;net462;netstandard2.1;net8.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net462;netstandard2.1;net8.0;net9.0</TargetFrameworks>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>annotations</Nullable>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;

Expand Down Expand Up @@ -87,7 +88,10 @@ private class SuffixExpressionVisitor : ExpressionVisitor

public SuffixExpressionVisitor(string suffix) => _suffix = suffix;

[RequiresDynamicCode("Use of Expression.Call requires dynamic code generation.")]
#pragma warning disable IL3051
public override Expression Visit(Expression node) => Expression.Call(
#pragma warning restore IL3051
typeof(SuffixExtensions),
nameof(SuffixExtensions.Suffix),
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ internal static class DynamicPropertyAccessor
// Build compiled getter delegate.

#pragma warning disable IL3050
#pragma warning disable IL2060
var getterDelegateFactory = MakeDelegateMethodInfo.MakeGenericMethod(type, getterMethod.ReturnType);
#pragma warning restore IL3050
#pragma warning restore IL2060
var genericGetterDelegate = (Func<object, object>)getterDelegateFactory.Invoke(null, [getterMethod])!;

return instance => retrieverFunc(genericGetterDelegate, instance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Runtime.CompilerServices;
using System.Text;
using System.Collections;
using System.Diagnostics.CodeAnalysis;

namespace Elastic.Clients.Elasticsearch;

Expand Down Expand Up @@ -61,6 +62,8 @@ protected override Expression VisitMember(MemberExpression expression)
return base.VisitMember(expression);
}

[RequiresDynamicCode("Use of Expression.Lambda")]
[UnconditionalSuppressMessage("Trimming", "IL3051", Justification = "Can only annotate our implementation")]
protected override Expression VisitMethodCall(MethodCallExpression methodCall)
{
if (methodCall.Method.Name == nameof(SuffixExtensions.Suffix) && methodCall.Arguments.Any())
Expand Down Expand Up @@ -97,6 +100,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCall)
return base.VisitMethodCall(methodCall);
}

[RequiresDynamicCode("Use of Expression.Lambda")]
private static void VisitConstantOrVariable(MethodCallExpression methodCall, Stack<string> stack)
{
var lastArg = methodCall.Arguments.Last();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elastic.Clients.Elasticsearch.Serialization;
Expand All @@ -27,6 +28,7 @@ public override void WriteAsPropertyName(Utf8JsonWriter writer, Id value, JsonSe
? new Id(reader.GetInt64())
: new Id(reader.GetString());

[UnconditionalSuppressMessage("AOT", "IL2072:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Call to object.GetType()")]
public override void Write(Utf8JsonWriter writer, Id value, JsonSerializerOptions options)
{
if (value is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;

namespace Elastic.Clients.Elasticsearch;

Expand All @@ -16,12 +17,11 @@ public class IdResolver
private readonly IElasticsearchClientSettings _settings;
private readonly ConcurrentDictionary<Type, Func<object, string?>?> _localDelegateCache = new();

public IdResolver(IElasticsearchClientSettings settings)
{
_settings = settings;
}
public IdResolver(IElasticsearchClientSettings settings) => _settings = settings;

public string? Resolve<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] T>(T instance)
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Call to object.GetType()")]
[UnconditionalSuppressMessage("AOT", "IL2072:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Call to object.GetType()")]
public string? Resolve<[DynamicallyAccessedMembers(PublicProperties | NonPublicProperties)] T>(T instance)
{
if (_settings.DefaultDisableIdInference || (instance is null))
{
Expand All @@ -31,7 +31,7 @@ public IdResolver(IElasticsearchClientSettings settings)
return Resolve(instance.GetType(), instance);
}

public string? Resolve([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type, object instance)
public string? Resolve([DynamicallyAccessedMembers(PublicProperties | NonPublicProperties)] Type type, object instance)
{
if (type is null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;

using Elastic.Transport;
using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;

namespace Elastic.Clients.Elasticsearch;

Expand Down Expand Up @@ -40,15 +41,15 @@ public Inferrer(IElasticsearchClientSettings elasticsearchClientSettings)

public string IndexName(IndexName index) => IndexNameResolver.Resolve(index);

public string? Id<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] T>(T instance) => IdResolver.Resolve(instance);
public string? Id<[DynamicallyAccessedMembers(PublicProperties | NonPublicProperties)] T>(T instance) => IdResolver.Resolve(instance);

public string? Id([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type, object instance) => IdResolver.Resolve(type, instance);
public string? Id([DynamicallyAccessedMembers(PublicProperties | NonPublicProperties)] Type type, object instance) => IdResolver.Resolve(type, instance);

public string RelationName<T>() => RelationNameResolver.Resolve<T>();

public string RelationName(RelationName type) => RelationNameResolver.Resolve(type);

public string? Routing<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] T>(T document) => RoutingResolver.Resolve(document);
public string? Routing<[DynamicallyAccessedMembers(PublicProperties | NonPublicProperties)] T>(T document) => RoutingResolver.Resolve(document);

public string? Routing([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type, object instance) => RoutingResolver.Resolve(type, instance);
public string? Routing([DynamicallyAccessedMembers(PublicProperties | NonPublicProperties)] Type type, object instance) => RoutingResolver.Resolve(type, instance);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elastic.Clients.Elasticsearch.Serialization;
Expand All @@ -18,6 +19,7 @@ internal sealed class RoutingConverter : JsonConverter<Routing>
? new Routing(reader.GetInt64())
: new Routing(reader.GetString());

[UnconditionalSuppressMessage("AOT", "IL2072:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Call to object.GetType()")]
public override void Write(Utf8JsonWriter writer, Routing value, JsonSerializerOptions options)
{
if (value is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Reflection;
using System.Linq;
using System.Globalization;
using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;

namespace Elastic.Clients.Elasticsearch;

Expand All @@ -23,7 +24,9 @@ public RoutingResolver(IElasticsearchClientSettings settings, IdResolver idResol
_settings = settings;
}

public string? Resolve<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] T>(T instance)
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Call to object.GetType()")]
[UnconditionalSuppressMessage("AOT", "IL2072:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Call to object.GetType()")]
public string? Resolve<[DynamicallyAccessedMembers(PublicProperties | None | NonPublicProperties)] T>(T instance)
{
if (instance is null)
{
Expand All @@ -33,7 +36,8 @@ public RoutingResolver(IElasticsearchClientSettings settings, IdResolver idResol
return Resolve(instance.GetType(), instance);
}

public string? Resolve([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type, object instance)
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Call to object.GetType()")]
public string? Resolve([DynamicallyAccessedMembers(PublicProperties | None | NonPublicProperties)] Type type, object instance)
{
if (type is null)
{
Expand All @@ -59,7 +63,7 @@ public RoutingResolver(IElasticsearchClientSettings settings, IdResolver idResol
}

private bool TryGetConnectionSettingsRoute(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type,
[DynamicallyAccessedMembers(PublicProperties | NonPublicProperties)] Type type,
object instance,
out string? route)
{
Expand All @@ -83,7 +87,7 @@ private bool TryGetConnectionSettingsRoute(
}

private static JoinField? GetJoinFieldFromObject(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type,
[DynamicallyAccessedMembers(PublicProperties | NonPublicProperties)] Type type,
object instance)
{
if (JoinFieldDelegateCache.TryGetValue(type, out var getterDelegate))
Expand All @@ -105,7 +109,7 @@ private bool TryGetConnectionSettingsRoute(

return getterDelegate(instance);

static PropertyInfo? GetJoinFieldProperty([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type)
static PropertyInfo? GetJoinFieldProperty([DynamicallyAccessedMembers(PublicProperties)] Type type)
{
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
Expand Down Expand Up @@ -141,15 +142,15 @@ private static IReadOnlyCollection<JsonConverter> CreateDefaultBuiltInConverters
new StringifiedDoubleConverter(),
];

[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Always using explicit TypeInfoResolver")]
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute'", Justification = "Always using explicit TypeInfoResolver")]
private static void MutateOptions(JsonSerializerOptions options)
{
#pragma warning disable IL2026, IL3050
options.TypeInfoResolver = JsonTypeInfoResolver.Combine(
RequestResponseSerializerContext.Default,
ElasticsearchTransportSerializerContext.Default,
new DefaultJsonTypeInfoResolver()
);
#pragma warning restore IL2026, IL3050

options.MaxDepth = 512;
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
Expand Down Expand Up @@ -79,23 +80,23 @@ public DefaultSourceSerializerOptionsProvider(IElasticsearchClientSettings setti
/// <summary>
/// Returns an array of the built-in <see cref="JsonConverter"/>s that are registered with the source serializer by default.
/// </summary>
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Always using explicit TypeInfoResolver")]
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute'", Justification = "Always using explicit TypeInfoResolver")]
private static IReadOnlyCollection<JsonConverter> CreateDefaultBuiltInConverters(IElasticsearchClientSettings settings) =>
[
// For context aware JsonConverter/JsonConverterFactory implementations.
new ContextProvider<IElasticsearchClientSettings>(settings),

#pragma warning disable IL3050
new JsonStringEnumConverter(),
#pragma warning restore IL3050
new DoubleWithFractionalPortionConverter(),
new SingleWithFractionalPortionConverter()
];

[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute'", Justification = "Always using explicit TypeInfoResolver")]
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute'", Justification = "Always using explicit TypeInfoResolver")]
private static void MutateOptions(JsonSerializerOptions options, IJsonTypeInfoResolver? typeInfoResolver, Action<JsonSerializerOptions>? configureOptions)
{
#pragma warning disable IL2026, IL3050
options.TypeInfoResolver = typeInfoResolver ?? new DefaultJsonTypeInfoResolver();
#pragma warning restore IL2026, IL3050

options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
Expand Down
2 changes: 1 addition & 1 deletion src/Playground/Playground.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
Expand Down
24 changes: 24 additions & 0 deletions src/Playground/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

using System.Diagnostics.CodeAnalysis;
using Elastic.Clients.Elasticsearch;
using Elastic.Transport;
using Elastic.Transport.Extensions;
using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;

using Playground;

Expand All @@ -18,3 +21,24 @@

var client = new ElasticsearchClient(settings);

var person = new Person
{
FirstName = "Steve",
LastName = "Jobs",
Age = 35,
IsDeleted = false,
Routing = "1234567890",
Id = 1,
Enum = DateTimeKind.Utc,
};

var id = client.Infer.Id(person);
var idByType = IdByType(person.GetType(), person);
Console.WriteLine(id);
Console.WriteLine(idByType);
// This still errors on AOT compilation
//Console.WriteLine(client.SourceSerializer.SerializeToString(person));

[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Can only annotate our implementation")]
[UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "Can only annotate our implementation")]
string? IdByType(Type type, object instance) => client.Infer.Id(type, instance);