Reflection, Attributes and Metadata
23.1 Reflection
Plugin isolation and unloading: AssemblyLoadContext (with isCollectible:=True) on modern .NET.
Imports System.Reflection
Dim t = GetType(Account)
Console.WriteLine($"{t.FullName} in {t.Assembly.GetName().Name}")
For Each p In t.GetProperties(BindingFlags.Public Or BindingFlags.Instance)
Console.WriteLine($"{p.Name}: {p.PropertyType.Name} (CanWrite={p.CanWrite})")
Next
Dim instance = Activator.CreateInstance(t, "Ana")
Dim deposit = t.GetMethod("Deposit")
deposit.Invoke(instance, New Object() {100D})
Dim balance = t.GetProperty("Balance").GetValue(instance)
' Plugin discovery
Dim pluginTypes = From asm In AppDomain.CurrentDomain.GetAssemblies()
From pt In asm.GetTypes()
Where GetType(IPlugin).IsAssignableFrom(pt) AndAlso Not pt.IsAbstract AndAlso Not pt.IsInterface
Select pt23.2 Attributes
Assembly attributes: <Assembly: AssemblyVersion("1.0.*")>, <Assembly: InternalsVisibleTo("X")>, <Assembly: CLSCompliant(True)>.
Caller info: <CallerMemberName>, <CallerFilePath>, <CallerLineNumber>, <CallerArgumentExpression> (consumed).
<AttributeUsage(AttributeTargets.Property)>
Public NotInheritable Class DisplayNameAttribute
Inherits Attribute
Public ReadOnly Property Text As String
Public Sub New(text As String)
Me.Text = text
End Sub
End Class
Public Class Customer
<DisplayName("Customer Name"), ComponentModel.DataAnnotations.Required, ComponentModel.DataAnnotations.StringLength(100)>
Public Property Name As String
End Class
Dim headers = From p In GetType(Customer).GetProperties()
Let a = p.GetCustomAttribute(Of DisplayNameAttribute)()
Select If(a?.Text, p.Name)
' Validate with DataAnnotations
Dim ctx As New ComponentModel.DataAnnotations.ValidationContext(customer)
Dim errors As New List(Of ComponentModel.DataAnnotations.ValidationResult)
Dim isValid = ComponentModel.DataAnnotations.Validator.TryValidateObject(customer, ctx, errors, validateAllProperties:=True)