Skip to content
6 changes: 3 additions & 3 deletions Source/ExcelDna.Integration/ExcelDna.Integration.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
</ItemGroup>

<ItemGroup>
<None Include="Registration\ExtendedFunc.cs">
<None Include="ExtendedFunc.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ExtendedFunc.tt</DependentUpon>
Expand All @@ -57,7 +57,7 @@
</ItemGroup>

<ItemGroup>
<None Update="Registration\ExtendedFunc.tt">
<None Update="ExtendedFunc.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ExtendedFunc.cs</LastGenOutput>
</None>
Expand All @@ -68,7 +68,7 @@
</ItemGroup>

<ItemGroup>
<Compile Update="Registration\ExtendedFunc.cs">
<Compile Update="ExtendedFunc.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ExtendedFunc.tt</DependentUpon>
Expand Down
2,076 changes: 2,076 additions & 0 deletions Source/ExcelDna.Integration/ExtendedFunc.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<# int maxArguments = 255; #>
#if !AOT_COMPATIBLE

using System;

namespace ExcelDna.Registration
namespace ExcelDna.Integration
{
internal class ExtendedFuncUtil
{
Expand Down Expand Up @@ -47,11 +46,10 @@ namespace ExcelDna.Registration
<# types +=$"T{k}{(k != i ? "," : "")}"; #>
<# args += $"T{k} arg{k}{(k !=i ?"," : "")}"; #>
<# } #>
internal delegate TResult ExtendedFunc<# Write(i.ToString());#><<# Write(types + (i > 0 ? "," : ""));#>TResult>
public delegate TResult ExtendedFunc<# Write(i.ToString());#><<# Write(types + (i > 0 ? "," : ""));#>TResult>
(<# Write(args);#>);
internal delegate void ExtendedAction<# Write(i.ToString());#><# Write((i > 0 ? "<" : "") + types + (i > 0 ? ">" : ""));#>
public delegate void ExtendedAction<# Write(i.ToString());#><# Write((i > 0 ? "<" : "") + types + (i > 0 ? ">" : ""));#>
(<# Write(args);#>);
<# } #>
}

#endif
2 changes: 1 addition & 1 deletion Source/ExcelDna.Integration/ObjectHandles/LazyLambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static LambdaExpression Create(LambdaExpression source)
var lazyLambdaConstructor = typeof(LazyLambda).GetConstructor(new Type[] { typeof(LambdaExpression), typeof(object[]) });
var parametersArray = Expression.NewArrayInit(typeof(object), wrappingParameters.Select(p => Expression.Convert(p, typeof(object))));
var wrappingCall = Expression.New(lazyLambdaConstructor, new Expression[] { Expression.Constant(source), parametersArray });
return Expression.Lambda(wrappingCall, wrappingParameters);
return Registration.ExcelFunctionRegistration.CreateLambdaWithAotContext(wrappingCall, "LazyLambda", wrappingParameters, "ObjectHandles");
}

public LazyLambda(LambdaExpression exp, params object[] args)
Expand Down
10 changes: 5 additions & 5 deletions Source/ExcelDna.Integration/Registration/AsyncRegistration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ static LambdaExpression WrapMethodRunTask(LambdaExpression functionLambda, List<
var callTaskRun = Expression.Call(runMethod, nameExp, paramsArrayExp, innerLambda);

// Wrap with all the parameters
return Expression.Lambda(callTaskRun, functionLambda.Name, newParams);
return ExcelFunctionRegistration.CreateLambdaWithAotContext(callTaskRun, functionLambda.Name, newParams, "AsyncRegistration");
}

#if AOT_COMPATIBLE
Expand Down Expand Up @@ -267,7 +267,7 @@ static LambdaExpression WrapMethodRunTaskWithCancellation(LambdaExpression funct
var callTaskRun = Expression.Call(runMethod, nameExp, paramsArrayExp, innerLambda);

// Wrap with all the parameters, and Compile to a Delegate
return Expression.Lambda(callTaskRun, functionLambda.Name, newParams);
return ExcelFunctionRegistration.CreateLambdaWithAotContext(callTaskRun, functionLambda.Name, newParams, "AsyncRegistration");
}

static LambdaExpression WrapMethodNativeAsyncTask(LambdaExpression functionLambda)
Expand Down Expand Up @@ -320,7 +320,7 @@ static LambdaExpression WrapMethodNativeAsyncTask(LambdaExpression functionLambd

// Wrap with all the parameters
var allParams = new List<ParameterExpression>(newParams) { asyncHandleParam };
return Expression.Lambda(callTaskRun, functionLambda.Name, allParams);
return ExcelFunctionRegistration.CreateLambdaWithAotContext(callTaskRun, functionLambda.Name, allParams, "AsyncRegistration");
#endif
}

Expand Down Expand Up @@ -381,7 +381,7 @@ static LambdaExpression WrapMethodNativeAsyncTaskWithCancellation(LambdaExpressi

// Wrap with all the parameters, and Compile to a Delegate
var allParams = new List<ParameterExpression>(newParams) { asyncHandleParam };
return Expression.Lambda(callTaskRun, functionLambda.Name, allParams);
return ExcelFunctionRegistration.CreateLambdaWithAotContext(callTaskRun, functionLambda.Name, allParams, "AsyncRegistration");
#endif
}

Expand Down Expand Up @@ -438,7 +438,7 @@ static LambdaExpression WrapMethodObservable(LambdaExpression functionLambda, Li
var callTaskRun = Expression.Call(obsMethod, nameExp, paramsArrayExp, innerLambda);

// Wrap with all the parameters, and Compile to a Delegate
return Expression.Lambda(callTaskRun, functionLambda.Name, newParams);
return ExcelFunctionRegistration.CreateLambdaWithAotContext(callTaskRun, functionLambda.Name, newParams, "AsyncRegistration");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Expr = System.Linq.Expressions.Expression;

namespace ExcelDna.Registration
{
Expand Down Expand Up @@ -145,27 +146,41 @@ public ExcelFunctionRegistration(MethodInfo methodInfo)
Debug.Assert(IsValid());
}

private static LambdaExpression CreateMethodLambda(MethodInfo methodInfo, IReadOnlyList<ParameterExpression> paramExprs)
{
try
{
return Expression.Lambda(GetExtendedDelegateType(methodInfo), Expression.Call(methodInfo, paramExprs), methodInfo.Name, paramExprs);
}
catch (NotSupportedException ex) when (IsMissingNativeMetadata(ex))
{
throw new InvalidOperationException(
$"NativeAOT could not build a registration expression for '{methodInfo.DeclaringType?.FullName}.{methodInfo.Name}'. " +
"The required Expression<TDelegate> shape is missing native metadata. " +
"Ensure the NativeAOT source generator roots Expression<Func<...>> / Expression<Action<...>> for this signature.",
ex);
}
}

#if AOT_COMPATIBLE
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL3050:RequiresDynamicCode", Justification = "SourceGenerator roots required Expression<TDelegate> shapes")]
#endif
private static LambdaExpression CreateMethodLambda(MethodInfo methodInfo, IReadOnlyList<ParameterExpression> paramExprs)
internal static LambdaExpression CreateLambdaWithAotContext(Expression body, string lambdaName, IEnumerable<ParameterExpression> parameters, string operation)
{
try
{
#if !AOT_COMPATIBLE
if (paramExprs.Count > 16)
{
return Expression.Lambda(GetExtendedDelegateType(methodInfo), Expression.Call(methodInfo, paramExprs), methodInfo.Name, paramExprs);
}
#if AOT_COMPATIBLE
if (parameters.Count() > 16)
return Expr.Lambda(GetExtendedDelegateType(parameters, body.Type), body, lambdaName, parameters);
#endif
return Expression.Lambda(Expression.Call(methodInfo, paramExprs), methodInfo.Name, paramExprs);
return Expr.Lambda(body, lambdaName, parameters);
}
catch (NotSupportedException ex) when (IsMissingNativeMetadata(ex))
{
throw new InvalidOperationException(
$"NativeAOT could not build a registration expression for '{methodInfo.DeclaringType?.FullName}.{methodInfo.Name}'. " +
$"NativeAOT could not build an expression during '{operation}' for '{lambdaName}'. " +
"The required Expression<TDelegate> shape is missing native metadata. " +
"Ensure the NativeAOT source generator roots Expression<Func<...>> / Expression<Action<...>> for this signature.",
"Ensure the NativeAOT source generator roots expression delegate shapes for rewritten registrations.",
ex);
}
}
Expand All @@ -175,7 +190,10 @@ static bool IsMissingNativeMetadata(NotSupportedException ex)
return ex.Message?.IndexOf("missing native code or metadata", StringComparison.OrdinalIgnoreCase) >= 0;
}

#if !AOT_COMPATIBLE
#if AOT_COMPATIBLE
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2055:RequiresUnreferencedCode", Justification = "SourceGenerator roots required Expression<TDelegate> shapes")]
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL3050:RequiresDynamicCode", Justification = "SourceGenerator roots required Expression<TDelegate> shapes")]
#endif
private static Type GetExtendedDelegateType(MethodInfo methodInfo)
{
if (methodInfo.ReturnType != typeof(void))
Expand All @@ -197,6 +215,18 @@ private static Type GetExtendedDelegateType(MethodInfo methodInfo)
return genericBase.MakeGenericType(args);
}
}

#if AOT_COMPATIBLE
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2055:RequiresUnreferencedCode", Justification = "SourceGenerator roots required Expression<TDelegate> shapes")]
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL3050:RequiresDynamicCode", Justification = "SourceGenerator roots required Expression<TDelegate> shapes")]
#endif
private static Type GetExtendedDelegateType(IEnumerable<ParameterExpression> parameters, Type returnType)
{
Type genericBase = ExtendedFuncUtil.GetFuncType(parameters.Count());
var args = parameters.Select(p => p.Type)
.Concat(new[] { returnType })
.ToArray();
return genericBase.MakeGenericType(args);
}
}
}
Loading