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
14 changes: 14 additions & 0 deletions Datadog.Trace.Build.g.sln
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks.Trace", "tracer\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.DuckTyping.Tests", "tracer\test\Datadog.Trace.DuckTyping.Tests\Datadog.Trace.DuckTyping.Tests.csproj", "{91E50134-0E55-4D22-B180-6967174FCE0B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.DuckTyping.Tests.Fixtures.Shared", "tracer\test\Datadog.Trace.DuckTyping.Tests.Fixtures\Shared\Datadog.Trace.DuckTyping.Tests.Fixtures.Shared.csproj", "{AF81B51B-C799-468D-9488-2D30C7A435B6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.DuckTyping.Tests.Fixtures.Target", "tracer\test\Datadog.Trace.DuckTyping.Tests.Fixtures\Target\Datadog.Trace.DuckTyping.Tests.Fixtures.Target.csproj", "{DE30EF39-4373-4485-8DC2-8CC08233CEA1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CallTargetNativeTest", "tracer\test\test-applications\instrumentation\CallTargetNativeTest\CallTargetNativeTest.csproj", "{021EFBA6-C4BA-4DE5-BF3F-C263EE9E20DB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.AspNet472.LoaderOptimizationRegKey", "tracer\test\test-applications\aspnet\Samples.AspNet472.LoaderOptimizationRegKey\Samples.AspNet472.LoaderOptimizationRegKey.csproj", "{BBB60B0F-BF01-4499-936A-4A299A9ACFD4}"
Expand Down Expand Up @@ -369,6 +373,14 @@ Global
{91E50134-0E55-4D22-B180-6967174FCE0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91E50134-0E55-4D22-B180-6967174FCE0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91E50134-0E55-4D22-B180-6967174FCE0B}.Release|Any CPU.Build.0 = Release|Any CPU
{AF81B51B-C799-468D-9488-2D30C7A435B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF81B51B-C799-468D-9488-2D30C7A435B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF81B51B-C799-468D-9488-2D30C7A435B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF81B51B-C799-468D-9488-2D30C7A435B6}.Release|Any CPU.Build.0 = Release|Any CPU
{DE30EF39-4373-4485-8DC2-8CC08233CEA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE30EF39-4373-4485-8DC2-8CC08233CEA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE30EF39-4373-4485-8DC2-8CC08233CEA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE30EF39-4373-4485-8DC2-8CC08233CEA1}.Release|Any CPU.Build.0 = Release|Any CPU
{021EFBA6-C4BA-4DE5-BF3F-C263EE9E20DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{021EFBA6-C4BA-4DE5-BF3F-C263EE9E20DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{021EFBA6-C4BA-4DE5-BF3F-C263EE9E20DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -602,6 +614,8 @@ Global
{C00D8070-A38A-4267-9730-E9985CAE77DF} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB}
{B8D132F6-43E3-44D9-902C-78051DBAD01C} = {E5439139-6F94-44FA-9590-C32FCC1C7A93}
{91E50134-0E55-4D22-B180-6967174FCE0B} = {8CEC2042-F11C-49F5-A674-2355793B600A}
{AF81B51B-C799-468D-9488-2D30C7A435B6} = {8CEC2042-F11C-49F5-A674-2355793B600A}
{DE30EF39-4373-4485-8DC2-8CC08233CEA1} = {8CEC2042-F11C-49F5-A674-2355793B600A}
{021EFBA6-C4BA-4DE5-BF3F-C263EE9E20DB} = {933F1D4B-1216-4BC1-956E-8C30818BAA0F}
{BBB60B0F-BF01-4499-936A-4A299A9ACFD4} = {AFA0AB23-64F0-4AC1-9050-6CE8FE06F580}
{78004AA7-26DD-44DB-A2C7-C287A5BBE5D6} = {A0C5FBBB-CFB2-4FB9-B8F0-55676E9DCF06}
Expand Down
14 changes: 14 additions & 0 deletions Datadog.Trace.sln
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependency-libs", "dependen
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.DuckTyping.Tests", "tracer\test\Datadog.Trace.DuckTyping.Tests\Datadog.Trace.DuckTyping.Tests.csproj", "{91E50134-0E55-4D22-B180-6967174FCE0B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.DuckTyping.Tests.Fixtures.Shared", "tracer\test\Datadog.Trace.DuckTyping.Tests.Fixtures\Shared\Datadog.Trace.DuckTyping.Tests.Fixtures.Shared.csproj", "{AF81B51B-C799-468D-9488-2D30C7A435B6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.DuckTyping.Tests.Fixtures.Target", "tracer\test\Datadog.Trace.DuckTyping.Tests.Fixtures\Target\Datadog.Trace.DuckTyping.Tests.Fixtures.Target.csproj", "{DE30EF39-4373-4485-8DC2-8CC08233CEA1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{A0C5FBBB-CFB2-4FB9-B8F0-55676E9DCF06}"
ProjectSection(SolutionItems) = preProject
tracer\build\PackageVersionsGeneratorDefinitions.json = tracer\build\PackageVersionsGeneratorDefinitions.json
Expand Down Expand Up @@ -871,6 +875,14 @@ Global
{91E50134-0E55-4D22-B180-6967174FCE0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91E50134-0E55-4D22-B180-6967174FCE0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91E50134-0E55-4D22-B180-6967174FCE0B}.Release|Any CPU.Build.0 = Release|Any CPU
{AF81B51B-C799-468D-9488-2D30C7A435B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF81B51B-C799-468D-9488-2D30C7A435B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF81B51B-C799-468D-9488-2D30C7A435B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF81B51B-C799-468D-9488-2D30C7A435B6}.Release|Any CPU.Build.0 = Release|Any CPU
{DE30EF39-4373-4485-8DC2-8CC08233CEA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE30EF39-4373-4485-8DC2-8CC08233CEA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE30EF39-4373-4485-8DC2-8CC08233CEA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE30EF39-4373-4485-8DC2-8CC08233CEA1}.Release|Any CPU.Build.0 = Release|Any CPU
{D79491F0-CA92-439B-98CE-7AF9F57EBEB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D79491F0-CA92-439B-98CE-7AF9F57EBEB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D79491F0-CA92-439B-98CE-7AF9F57EBEB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -1661,6 +1673,8 @@ Global
{AFA0AB23-64F0-4AC1-9050-6CE8FE06F580} = {9518425A-36A5-4B8F-B0B8-6137DB88441D}
{8683D82A-2BBE-4199-9C36-C59F48804F90} = {BAF8F246-3645-42AD-B1D0-0F7EAFBAB34A}
{91E50134-0E55-4D22-B180-6967174FCE0B} = {8CEC2042-F11C-49F5-A674-2355793B600A}
{AF81B51B-C799-468D-9488-2D30C7A435B6} = {8CEC2042-F11C-49F5-A674-2355793B600A}
{DE30EF39-4373-4485-8DC2-8CC08233CEA1} = {8CEC2042-F11C-49F5-A674-2355793B600A}
{CC53E5C5-9D3E-4AD9-A9CA-D2190463EB5B} = {A0C5FBBB-CFB2-4FB9-B8F0-55676E9DCF06}
{E5439139-6F94-44FA-9590-C32FCC1C7A93} = {8CEC2042-F11C-49F5-A674-2355793B600A}
{D79491F0-CA92-439B-98CE-7AF9F57EBEB0} = {498A300E-D036-49B7-A43D-821D1CAF11A5}
Expand Down
2 changes: 2 additions & 0 deletions tracer/build/_build/Build.Steps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,8 @@ void PrepareMonitoringHomeLinuxForPackaging(AbsolutePath assetsDirectory, string
.Executes(() =>
{
//we need to build in this exact order
DotnetBuild(TracerDirectory.GlobFiles("test/Datadog.Trace.DuckTyping.Tests.Fixtures/Shared/*.csproj"));
DotnetBuild(TracerDirectory.GlobFiles("test/Datadog.Trace.DuckTyping.Tests.Fixtures/Target/*.csproj"));
DotnetBuild(TracerDirectory.GlobFiles("test/**/*TestHelpers.csproj"));
DotnetBuild(TracerDirectory.GlobFiles("test/**/*TestHelpers.AutoInstrumentation.csproj"));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,7 @@
</assembly>
<assembly fullname="System.Runtime.Loader">
<type fullname="System.Runtime.Loader.AssemblyLoadContext" />
<type fullname="System.Runtime.Loader.AssemblyLoadContext/ContextualReflectionScope" />
</assembly>
<assembly fullname="System.Runtime.Numerics">
<type fullname="System.Numerics.BigInteger" />
Expand Down
111 changes: 111 additions & 0 deletions tracer/src/Datadog.Trace/DuckTyping/DuckType.Statics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
#if NETCOREAPP3_1 || NET6_0_OR_GREATER
using System.Runtime.Loader;
#endif
// ReSharper disable InconsistentNaming

namespace Datadog.Trace.DuckTyping
Expand Down Expand Up @@ -40,6 +43,18 @@ public static partial class DuckType
private static readonly MethodInfo? _methodBuilderGetToken;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static readonly ConstructorInfo? _ignoresAccessChecksToAttributeCtor;
#if NETSTANDARD2_0 || NETCOREAPP3_1
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static readonly MethodInfo? _defineDynamicAssemblyMethodInfo;
#endif
#if NETSTANDARD2_0
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static readonly MethodInfo? _getAssemblyLoadContextMethodInfo;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static readonly object? _duckTypeAssemblyLoadContext;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static readonly Dictionary<Assembly, bool> AssembliesInDuckTypeLoadContext;
#endif

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static long _assemblyCount;
Expand All @@ -59,6 +74,15 @@ static DuckType()
_methodBuilderGetToken = typeof(MethodBuilder).GetMethod("GetToken", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
?? typeof(MethodBuilder).GetProperty("MetadataToken", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)?.GetMethod;
_ignoresAccessChecksToAttributeCtor = typeof(IgnoresAccessChecksToAttribute).GetConstructor(new[] { typeof(string) });
#if NETSTANDARD2_0 || NETCOREAPP3_1
_defineDynamicAssemblyMethodInfo = typeof(AssemblyBuilder).GetMethod(nameof(AssemblyBuilder.DefineDynamicAssembly), new[] { typeof(AssemblyName), typeof(AssemblyBuilderAccess) });
#endif
#if NETSTANDARD2_0
var assemblyLoadContextType = Type.GetType("System.Runtime.Loader.AssemblyLoadContext, System.Runtime.Loader", throwOnError: false);
_getAssemblyLoadContextMethodInfo = assemblyLoadContextType?.GetMethod("GetLoadContext", BindingFlags.Public | BindingFlags.Static, binder: null, [typeof(Assembly)], modifiers: null);
_duckTypeAssemblyLoadContext = _getAssemblyLoadContextMethodInfo?.Invoke(obj: null, [typeof(DuckType).Assembly]);
AssembliesInDuckTypeLoadContext = new();
#endif

_assemblyCount = 0;
_typeCount = 0;
Expand Down Expand Up @@ -139,6 +163,21 @@ private static ConstructorInfo IgnoresAccessChecksToAttributeCtor
}
}

#if NETSTANDARD2_0 || NETCOREAPP3_1
private static MethodInfo DefineDynamicAssemblyMethodInfo
{
get
{
if (_defineDynamicAssemblyMethodInfo is null)
{
DuckTypeException.Throw($"{nameof(AssemblyBuilder)}.{nameof(AssemblyBuilder.DefineDynamicAssembly)}() cannot be found.");
}

return _defineDynamicAssemblyMethodInfo;
}
}
#endif

/// <summary>
/// Gets the ModuleBuilder instance from a target type. (.NET Framework / Non AssemblyLoadContext version)
/// </summary>
Expand Down Expand Up @@ -180,9 +219,81 @@ static ModuleBuilder CreateModuleBuilder(string name, Assembly targetAssembly)
{
var assemblyName = new AssemblyName(name + $"_{++_assemblyCount}");
assemblyName.Version = targetAssembly.GetName().Version;

#if NET6_0_OR_GREATER
Comment thread
tonyredondo marked this conversation as resolved.
AssemblyBuilder assemblyBuilder;
if (IsAssemblyInCurrentLoadContext(targetAssembly))
{
assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
}
else
{
using var contextualReflectionScope = AssemblyLoadContext.EnterContextualReflection(targetAssembly);
assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
}
#elif NETSTANDARD2_0 || NETCOREAPP3_1
var assemblyBuilder = IsAssemblyInCurrentLoadContext(targetAssembly)
? AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run)
: DefineDynamicAssemblyInTargetLoadContext(assemblyName, targetAssembly.ManifestModule);
#else
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
#endif
return assemblyBuilder.DefineDynamicModule("MainModule");
}

#if NETCOREAPP3_1 || NET6_0_OR_GREATER
static bool IsAssemblyInCurrentLoadContext(Assembly targetAssembly)
{
#if NET6_0_OR_GREATER
var currentLoadContext = AssemblyLoadContext.CurrentContextualReflectionContext
?? AssemblyLoadContext.GetLoadContext(typeof(DuckType).Assembly);
#else
var currentLoadContext = AssemblyLoadContext.GetLoadContext(typeof(DuckType).Assembly);
#endif
return ReferenceEquals(AssemblyLoadContext.GetLoadContext(targetAssembly), currentLoadContext);
}
#elif NETSTANDARD2_0
static bool IsAssemblyInCurrentLoadContext(Assembly targetAssembly)
{
// AssemblyLoadContext is not part of the .NET Standard 2.0 contract. Resolve it at runtime
// so the fast path does not add a System.Runtime.Loader dependency to Datadog.Trace.
if (_getAssemblyLoadContextMethodInfo is null)
{
return true;
}

if (!AssembliesInDuckTypeLoadContext.TryGetValue(targetAssembly, out var isInDuckTypeLoadContext))
{
var targetAssemblyLoadContext = _getAssemblyLoadContextMethodInfo.Invoke(obj: null, [targetAssembly]);
isInDuckTypeLoadContext = ReferenceEquals(targetAssemblyLoadContext, _duckTypeAssemblyLoadContext);
AssembliesInDuckTypeLoadContext.Add(targetAssembly, isInDuckTypeLoadContext);
}

return isInDuckTypeLoadContext;
}
#endif

#if NETSTANDARD2_0 || NETCOREAPP3_1
static AssemblyBuilder DefineDynamicAssemblyInTargetLoadContext(AssemblyName assemblyName, Module targetModule)
{
// Before .NET 6, DefineDynamicAssembly does not honor contextual reflection. Associating the
// call site with the target module makes the runtime create the proxy in the target load context.
var createAssemblyMethod = new DynamicMethod(
"CreateDuckTypeAssembly",
typeof(AssemblyBuilder),
[typeof(AssemblyName)],
targetModule,
skipVisibility: false);
var il = createAssemblyMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, (int)AssemblyBuilderAccess.Run);
il.Emit(OpCodes.Call, DefineDynamicAssemblyMethodInfo);
il.Emit(OpCodes.Ret);

var createAssembly = (Func<AssemblyName, AssemblyBuilder>)createAssemblyMethod.CreateDelegate(typeof(Func<AssemblyName, AssemblyBuilder>));
return createAssembly(assemblyName);
}
#endif
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Project>
<Import Project="..\..\Directory.Build.props" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsTestProject>false</IsTestProject>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// <copyright file="FieldValue.cs" company="Datadog">
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

namespace Datadog.Trace.DuckTyping.Tests.Fixtures.Shared;

public sealed class FieldValue
{
public const int ExpectedValue = 42;

public int Value => ExpectedValue;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsTestProject>false</IsTestProject>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Shared\Datadog.Trace.DuckTyping.Tests.Fixtures.Shared.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// <copyright file="DuckTypingTarget.cs" company="Datadog">
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

using Datadog.Trace.DuckTyping.Tests.Fixtures.Shared;

namespace Datadog.Trace.DuckTyping.Tests.Fixtures.Target;

public sealed class DuckTypingTarget
{
private readonly FieldValue _field = new();

public object FieldValue => _field;
}
Loading
Loading