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
Original file line number Diff line number Diff line change
@@ -1,74 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CustomAttributes
using System.Reflection;

namespace CustomAttributes;

public static class CustomAttributeHelper
{
public static class CustomAttributeHelper
private static void WriteOnTheConsole(Attribute attributeInstance)
{
private static void WriteOnTheConsole(Attribute attributeInstance)
{
var pInfoList = attributeInstance.GetType().GetProperties(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);
var pInfoList = attributeInstance.GetType().GetProperties(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);

Console.WriteLine($"\nThe {attributeInstance} attribute:");
Console.WriteLine($"\nThe {attributeInstance} attribute:");

foreach (var pInfo in pInfoList)
Console.WriteLine($"The {pInfo.Name} property is: {pInfo.GetValue(attributeInstance)}");
}
foreach (var pInfo in pInfoList)
Console.WriteLine($"The {pInfo.Name} property is: {pInfo.GetValue(attributeInstance)}");
}

public static string? GetAttribute(Type desiredType, Type desiredAttribute)
{
var attributeInstance = Attribute.GetCustomAttribute(desiredType, desiredAttribute);
public static string? GetAttribute(Type desiredType, Type desiredAttribute)
{
var attributeInstance = Attribute.GetCustomAttribute(desiredType, desiredAttribute);

if (attributeInstance == null)
Console.WriteLine($"The class {desiredType} does not have atributes.");
else
WriteOnTheConsole(attributeInstance);
if (attributeInstance == null)
Console.WriteLine($"The class {desiredType} does not have attributes.");
else
WriteOnTheConsole(attributeInstance);

return attributeInstance?.ToString();
}
return attributeInstance?.ToString();
}

public static T? GetAttributeGeneric<T>(Type desiredType) where T : Attribute
{
return desiredType.GetCustomAttribute<T>();
}

public static bool HasAttribute<T>(Type desiredType) where T : Attribute
{
return desiredType.IsDefined(typeof(T));
}

public static List<string> GetAttributesOfMethods(Type elementType)
public static List<string> GetAttributesOfMethods(Type elementType)
{
var attributes = new List<string>();

var methodInfoList = elementType.GetMethods(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);

if (methodInfoList.Length == 0)
{
List<string> attributes = new List<string>();
Console.WriteLine($"The type {elementType} does not have any methods.");
return attributes;
}

var methodInfoList = elementType.GetMethods(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);
foreach (var methodInfo in methodInfoList)
{
var attributeList = Attribute.GetCustomAttributes(methodInfo, true);

if (methodInfoList == null || methodInfoList.Length == 0)
if (attributeList.Length == 0)
{
Console.WriteLine($"The type {elementType} does not have any methods.");
return attributes;
Console.WriteLine($"The {elementType.Name}.{methodInfo.Name} method does not have attributes.");
continue;
}

foreach (var methodInfo in methodInfoList)
{
var attributeList = Attribute.GetCustomAttributes(methodInfo, true);
Console.WriteLine($"The {elementType.Name}.{methodInfo.Name} method's attribute:");

if (attributeList.Length == 0)
{
Console.WriteLine($"The {elementType.Name}.{methodInfo.Name} method does not have attributes.");
continue;
}
foreach (var att in attributeList)
{
WriteOnTheConsole(att);
attributes.Add(methodInfo.Name + "-" + att.ToString());
}

Console.WriteLine($"The {elementType.Name}.{methodInfo.Name} method's attribute:");
Console.WriteLine();
}

foreach (var att in attributeList)
{
WriteOnTheConsole(att);
attributes.Add(methodInfo.Name + "-" + att.ToString());
}
return attributes;
}

Console.WriteLine();
}
public static (int FromAttributeClass, int FromMember) CountInheritedAttributes<T>(MemberInfo member)
where T : Attribute
{
var fromAttributeClass = Attribute.GetCustomAttributes(member, true).OfType<T>().Count();
var fromMember = member.GetCustomAttributes(true).OfType<T>().Count();

return attributes;
}
return (fromAttributeClass, fromMember);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CustomAttributes;

namespace CustomAttributes
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DeveloperTaskAttribute : Attribute
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DeveloperTaskAttribute : Attribute
public DeveloperTaskAttribute(Priorities priority)
{
public DeveloperTaskAttribute(Priorities priority)
{
Priority = priority;
}

public Priorities Priority { get; set; }
public string? Description { get; set; }
Priority = priority;
}

public Priorities Priority { get; set; }
public string? Description { get; set; }
}
17 changes: 5 additions & 12 deletions aspnetcore-features/CustomAttributes/CustomAttributes/Enums.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CustomAttributes;

namespace CustomAttributes
public enum Priorities
{
public enum Priorities
{
High,
Mid,
Low
}
High,
Mid,
Low
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CustomAttributes;

namespace CustomAttributes
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class ManagerTaskAttribute : Attribute
{
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class ManagerTaskAttribute : Attribute
{
public Priorities Priority { get; set; }
public bool NeedsReport { get; set; }
}
public Priorities Priority { get; set; }
public bool NeedsReport { get; set; }
}
35 changes: 14 additions & 21 deletions aspnetcore-features/CustomAttributes/CustomAttributes/MyTasks.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CustomAttributes;

namespace CustomAttributes
[TaskDescriptor(Name = "The task's name",
Description = "Some descriptions for the task",
NeedsManager = true,
DeveloperCount = 5)]
public class MyTasks
{
[TaskDescriptor(Name = "The task's name",
Description = "Some descriptions for the task",
NeedsManager = true,
DeveloperCount = 5)]
public class MyTasks
[DeveloperTask(Priorities.Low)]
[DeveloperTask(Priorities.High, Description = "High level description")]
public void ScheduleMeeting()
{
[DeveloperTask(Priorities.Low)]
[DeveloperTask(Priorities.High, Description = "High level description")]
public void ScheduleMeeting()
{
}
}

[ManagerTask(Priority = Priorities.Mid, NeedsReport = true)]
[DeveloperTask(Priorities.High, Description = "High level description")]
public virtual void ScheduleInterview()
{
}
[ManagerTask(Priority = Priorities.Mid, NeedsReport = true)]
[DeveloperTask(Priorities.High, Description = "High level description")]
public virtual void ScheduleInterview()
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace CustomAttributes;

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
public class ReviewedAttribute : Attribute
{
}
12 changes: 12 additions & 0 deletions aspnetcore-features/CustomAttributes/CustomAttributes/TaskBoard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace CustomAttributes;

public class TaskBoard
{
[Reviewed]
public virtual int OpenTasks { get; set; }

[Reviewed]
public virtual void Archive()
{
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CustomAttributes;

namespace CustomAttributes
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class TaskDescriptorAttribute : Attribute
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class TaskDescriptorAttribute : Attribute
{
public string? Name { get; set; }
public string? Description { get; set; }
public bool NeedsManager { get; set; }
public int DeveloperCount { get; set; }
}
public string? Name { get; set; }
public string? Description { get; set; }
public bool NeedsManager { get; set; }
public int DeveloperCount { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace CustomAttributes;

public class TeamTaskBoard : TaskBoard
{
public override int OpenTasks { get; set; }

public override void Archive()
{
}
}
15 changes: 4 additions & 11 deletions aspnetcore-features/CustomAttributes/CustomAttributes/YourTasks.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CustomAttributes;

namespace CustomAttributes
public class YourTasks : MyTasks
{
public class YourTasks : MyTasks
[DeveloperTask(Priorities.Mid, Description = "Mid level description")]
public override void ScheduleInterview()
{
[DeveloperTask(Priorities.Mid, Description = "Mid level description")]
public override void ScheduleInterview()
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,37 @@ public void WhenCorrectYourTaskInput_ThenCorrectMultipleAttOutput()

Assert.IsTrue(result);
}

[TestMethod]
public void WhenGenericGetCustomAttribute_ThenTypedInstanceWithoutCast()
{
var descriptor = CustomAttributeHelper.GetAttributeGeneric<TaskDescriptorAttribute>(typeof(MyTasks));
var missing = CustomAttributeHelper.GetAttributeGeneric<ManagerTaskAttribute>(typeof(MyTasks));

Assert.IsNotNull(descriptor);
Assert.AreEqual("The task's name", descriptor.Name);
Assert.AreEqual(5, descriptor.DeveloperCount);
Assert.IsNull(missing);
}

[TestMethod]
public void WhenIsDefined_ThenTrueOnlyWhereTheAttributeIsApplied()
{
Assert.IsTrue(CustomAttributeHelper.HasAttribute<TaskDescriptorAttribute>(typeof(MyTasks)));
Assert.IsFalse(CustomAttributeHelper.HasAttribute<ManagerTaskAttribute>(typeof(MyTasks)));
}

[TestMethod]
public void WhenInheritIsTrue_ThenMemberGetCustomAttributesIgnoresItOnPropertiesOnly()
{
var property = typeof(TeamTaskBoard).GetProperty(nameof(TeamTaskBoard.OpenTasks))!;
var method = typeof(TeamTaskBoard).GetMethod(nameof(TeamTaskBoard.Archive))!;

var onProperty = CustomAttributeHelper.CountInheritedAttributes<ReviewedAttribute>(property);
var onMethod = CustomAttributeHelper.CountInheritedAttributes<ReviewedAttribute>(method);

Assert.AreEqual((1, 0), onProperty);
Assert.AreEqual((1, 1), onMethod);
}
}
}
Loading
Loading