public NotificationAttribute(NotificationUidType type, string key) { Type = type; Key = key; }
/// <summary> /// Constructor to create a notification with arbitrary parameters /// </summary> /// <param name="key">Notification Key to identify the type of notification</param> /// <param name="parameters">Some data that is specific to the notification</param> /// <param name="type">Type of Uid Provided (e.g Customer or Project)</param> public Notification(string key, object parameters, NotificationUidType type) { Key = key; Parameters = parameters; Type = type; }
/// <summary> /// Finds all methods in the currently loaded assemblies that match the Notification Type requested. /// </summary> private IEnumerable <MethodInfo> GetTypes(NotificationUidType uidType, string key) { List <MethodInfo> methods; lock (methodInfoLock) { if (methodInfoCache == null) { // Load the methods for the notification hub into a cached list. // Validate these at generation as well. var assemblies = AppDomain.CurrentDomain.GetAssemblies(); methodInfoCache = new List <MethodInfo>(); foreach (var assembly in assemblies) { try { var localMethods = assembly .GetTypes() .SelectMany(t => t.GetMethods()) .Where(m => m.GetCustomAttributes(typeof(NotificationAttribute), false).Length > 0) .ToList(); foreach (var method in localMethods) { if (!ValidateMethod(method)) { // We want to log an error, but still add the method to the cache // That way we still get errors if/when the event that triggers the method is generated. Logger.LogError($"Method {method.DeclaringType.FullName}::{method.Name} is invalid. " + $"It should be {typeof(void).Name}/{typeof(Task).Name} {method.Name}({typeof(Guid).FullName}) " + $"or {typeof(void).Name}/{typeof(Task).Name} {method.Name}({typeof(object).FullName})"); } } methodInfoCache.AddRange(localMethods); if (localMethods.Count > 0) { Logger.LogInformation($"Assembly: {assembly.GetName().Name} has Notification Methods: {string.Join(", ", localMethods.Select(m => m.Name))}"); } } catch (ReflectionTypeLoadException e) { // This is perfectly acceptable, happens with some .NET assemblies Logger.LogWarning($"Failed to load assembly {assembly.FullName} due to load exception, {e.Message}"); } } } methods = methodInfoCache; } foreach (var methodInfo in methods) { if (methodInfo.GetCustomAttributes <NotificationAttribute>().Any(a => a.Type == uidType && string.Compare(a.Key, key, StringComparison.OrdinalIgnoreCase) == 0)) { yield return(methodInfo); } } }
/// <summary> /// Constructor to create a notification /// </summary> /// <param name="key">Notification Key to identify the type of notification</param> /// <param name="uid">Uid for the Type (e.g ProjectUid or CustomerUid)</param> /// <param name="type">Type of Uid Provided (e.g Customer or Project)</param> public Notification(string key, Guid uid, NotificationUidType type) { Key = key; Uid = uid; Type = type; }