From 229905dfdcbd61207d4ac14895cd7b7af4d460c5 Mon Sep 17 00:00:00 2001
From: "A. Karboush" <40485241+akarboush@users.noreply.github.com>
Date: Sun, 18 Aug 2024 18:29:37 +0200
Subject: [PATCH] Add custom InjectLambdaAttribute provider
---
src/NeinLinq/InjectLambdaAttribute.cs | 30 ++++++++++++++++---
src/NeinLinq/InjectLambdaMetadata.cs | 8 ++---
.../InjectLambdaAttributeTest.cs | 20 +++++++++++++
3 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/src/NeinLinq/InjectLambdaAttribute.cs b/src/NeinLinq/InjectLambdaAttribute.cs
index f6387bb..acb3010 100644
--- a/src/NeinLinq/InjectLambdaAttribute.cs
+++ b/src/NeinLinq/InjectLambdaAttribute.cs
@@ -2,17 +2,26 @@
namespace NeinLinq;
+///
+/// Delegate for custom attribute providers.
+///
+/// The MemberInfo to get the attribute for.
+/// The InjectLambdaAttribute if found, otherwise null.
+public delegate InjectLambdaAttribute? InjectLambdaAttributeProvider(MemberInfo memberInfo);
+
///
/// Marks a method as injectable.
///
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false)]
public sealed class InjectLambdaAttribute : Attribute
{
- internal static InjectLambdaAttribute None { get; }
- = new InjectLambdaAttribute();
+ ///
+ /// Gets the current attribute provider. Default is the standard reflection-based provider.
+ ///
+ 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();
///
/// The target type for the method's expression. The current type, if null.
@@ -70,4 +79,17 @@ public InjectLambdaAttribute(string method)
Method = method;
}
+
+ ///
+ /// Sets a custom attribute provider.
+ ///
+ /// The custom attribute provider to set.
+ /// Thrown if provider is null.
+ public static void SetAttributeProvider(InjectLambdaAttributeProvider provider)
+ {
+ if (provider is null)
+ throw new ArgumentNullException(nameof(provider));
+
+ Provider = provider;
+ }
}
diff --git a/src/NeinLinq/InjectLambdaMetadata.cs b/src/NeinLinq/InjectLambdaMetadata.cs
index b084e23..fbd6e2d 100644
--- a/src/NeinLinq/InjectLambdaMetadata.cs
+++ b/src/NeinLinq/InjectLambdaMetadata.cs
@@ -20,7 +20,7 @@ private InjectLambdaMetadata(bool config, Lazy>(()
=> LambdaFactory(method, metadata ?? InjectLambdaAttribute.None));
@@ -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>(()
=> LambdaFactory(property, metadata ?? InjectLambdaAttribute.None));
@@ -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);
diff --git a/test/NeinLinq.Tests/InjectLambdaAttributeTest.cs b/test/NeinLinq.Tests/InjectLambdaAttributeTest.cs
index df61fe0..12383e5 100644
--- a/test/NeinLinq.Tests/InjectLambdaAttributeTest.cs
+++ b/test/NeinLinq.Tests/InjectLambdaAttributeTest.cs
@@ -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(() => 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);
+ }
}