Skip to content

Commit

Permalink
Add custom InjectLambdaAttribute provider
Browse files Browse the repository at this point in the history
  • Loading branch information
akarboush authored Aug 18, 2024
1 parent 4e5ae5b commit 229905d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 8 deletions.
30 changes: 26 additions & 4 deletions src/NeinLinq/InjectLambdaAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,26 @@

namespace NeinLinq;

/// <summary>
/// Delegate for custom attribute providers.
/// </summary>
/// <param name="memberInfo">The MemberInfo to get the attribute for.</param>
/// <returns>The InjectLambdaAttribute if found, otherwise null.</returns>
public delegate InjectLambdaAttribute? InjectLambdaAttributeProvider(MemberInfo memberInfo);

/// <summary>
/// Marks a method as injectable.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false)]
public sealed class InjectLambdaAttribute : Attribute
{
internal static InjectLambdaAttribute None { get; }
= new InjectLambdaAttribute();
/// <summary>
/// Gets the current attribute provider. Default is the standard reflection-based provider.
/// </summary>
public static InjectLambdaAttributeProvider Provider { get; private set; } = memberInfo
=> (InjectLambdaAttribute?)GetCustomAttribute(memberInfo, typeof(InjectLambdaAttribute));

internal static InjectLambdaAttribute? GetCustomAttribute(MemberInfo element)
=> (InjectLambdaAttribute?)GetCustomAttribute(element, typeof(InjectLambdaAttribute));
internal static InjectLambdaAttribute None { get; } = new InjectLambdaAttribute();

/// <summary>
/// The target type for the method's expression. The current type, if null.
Expand Down Expand Up @@ -70,4 +79,17 @@ public InjectLambdaAttribute(string method)

Method = method;
}

/// <summary>
/// Sets a custom attribute provider.
/// </summary>
/// <param name="provider">The custom attribute provider to set.</param>
/// <exception cref="ArgumentNullException">Thrown if provider is null.</exception>
public static void SetAttributeProvider(InjectLambdaAttributeProvider provider)
{
if (provider is null)
throw new ArgumentNullException(nameof(provider));

Provider = provider;
}
}
8 changes: 4 additions & 4 deletions src/NeinLinq/InjectLambdaMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private InjectLambdaMetadata(bool config, Lazy<Func<Expression?, LambdaExpressio

public static InjectLambdaMetadata Create(MethodInfo method)
{
var metadata = InjectLambdaAttribute.GetCustomAttribute(method);
var metadata = InjectLambdaAttribute.Provider(method);

var lambdaFactory = new Lazy<Func<Expression?, LambdaExpression?>>(()
=> LambdaFactory(method, metadata ?? InjectLambdaAttribute.None));
Expand All @@ -30,8 +30,8 @@ public static InjectLambdaMetadata Create(MethodInfo method)

public static InjectLambdaMetadata Create(PropertyInfo property)
{
var metadata = InjectLambdaAttribute.GetCustomAttribute(property)
?? InjectLambdaAttribute.GetCustomAttribute(property.GetGetMethod(true)!);
var metadata = InjectLambdaAttribute.Provider(property)
?? InjectLambdaAttribute.Provider(property.GetGetMethod(true)!);

var lambdaFactory = new Lazy<Func<Expression?, LambdaExpression?>>(()
=> LambdaFactory(property, metadata ?? InjectLambdaAttribute.None));
Expand Down Expand Up @@ -102,7 +102,7 @@ public static InjectLambdaMetadata Create(PropertyInfo property)
var concreteMethod = signature.FindMatch(targetType, method.Name, value!.Type)!;

// configuration over convention, if any
var metadata = InjectLambdaAttribute.GetCustomAttribute(concreteMethod) ?? InjectLambdaAttribute.None;
var metadata = InjectLambdaAttribute.Provider(concreteMethod) ?? InjectLambdaAttribute.None;

// retrieve validated factory method
var factoryMethod = signature.FindFactory(targetType, metadata.Method ?? method.Name, value.Type);
Expand Down
20 changes: 20 additions & 0 deletions test/NeinLinq.Tests/InjectLambdaAttributeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,24 @@ public void Ctor_NullArgument_Throws()
Assert.Equal("target", targetMethodError.ParamName);
Assert.Equal("method", methodTargetError.ParamName);
}

[Fact]
public void SetAttributeProvider_NullProvider_Throws()
{
var error = Assert.Throws<ArgumentNullException>(() => InjectLambdaAttribute.SetAttributeProvider(null!));

Assert.Equal("provider", error.ParamName);
}

[Fact]
public void SetAttributeProvider_SetsProvider()
{
var oldProvider = InjectLambdaAttribute.Provider;

InjectLambdaAttributeProvider newProvider = mem => oldProvider(mem);

InjectLambdaAttribute.SetAttributeProvider(newProvider);

Assert.Equal(InjectLambdaAttribute.Provider, newProvider);
}
}

0 comments on commit 229905d

Please sign in to comment.