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); + } }