Skip to content
Merged
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
86 changes: 64 additions & 22 deletions Sources/EventViewerX/EventObjectSlim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ public RuleFactoryRegistration(NamedEvents namedEvent, string logName, IReadOnly
public Type? RuleType { get; }
}

private static readonly Dictionary<NamedEvents, Type> _eventRuleTypes = new();
private static readonly Dictionary<(int EventId, string LogName), List<Type>> _eventHandlers = new();
private static readonly Dictionary<NamedEvents, Type> _reflectionRuleTypes = new();
private static readonly Dictionary<(int EventId, string LogName), List<Type>> _reflectionHandlers = new();

private static readonly Dictionary<NamedEvents, Type> _explicitRuleTypes = new();
private static readonly Dictionary<(int EventId, string LogName), List<Type>> _explicitHandlers = new();

// AOT-friendly path: explicit, delegate-based rule registration.
private static readonly Dictionary<NamedEvents, RuleFactoryRegistration> _ruleFactories = new();
Expand Down Expand Up @@ -145,7 +148,7 @@ public static void RegisterRuleFactory(
_ruleFactories[namedEvent] = reg;

if (ruleType is not null) {
_eventRuleTypes[namedEvent] = ruleType;
_explicitRuleTypes[namedEvent] = ruleType;
}

foreach (var eventId in ids) {
Expand All @@ -160,9 +163,9 @@ public static void RegisterRuleFactory(

if (ruleType is not null) {
var legacyKey = (eventId, normalizedLog);
if (!_eventHandlers.TryGetValue(legacyKey, out var legacyList)) {
if (!_explicitHandlers.TryGetValue(legacyKey, out var legacyList)) {
legacyList = new List<Type>();
_eventHandlers[legacyKey] = legacyList;
_explicitHandlers[legacyKey] = legacyList;
}
if (!legacyList.Contains(ruleType)) {
legacyList.Add(ruleType);
Expand Down Expand Up @@ -211,29 +214,29 @@ private static void RegisterEventRuleType(Type ruleType) {
#pragma warning disable SYSLIB0050
var instance = (EventRuleBase)System.Runtime.Serialization.FormatterServices.GetUninitializedObject(ruleType);
#pragma warning restore SYSLIB0050
_eventRuleTypes[instance.NamedEvent] = ruleType;
_reflectionRuleTypes[instance.NamedEvent] = ruleType;

foreach (var eventId in instance.EventIds) {
var key = (eventId, instance.LogName);
if (!_eventHandlers.ContainsKey(key)) {
_eventHandlers[key] = new List<Type>();
if (!_reflectionHandlers.ContainsKey(key)) {
_reflectionHandlers[key] = new List<Type>();
}
_eventHandlers[key].Add(ruleType);
_reflectionHandlers[key].Add(ruleType);
}
} catch {
return;
}
} else {
var attr = ruleType.GetCustomAttribute<EventRuleAttribute>();
if (attr != null) {
_eventRuleTypes[attr.NamedEvent] = ruleType;
_reflectionRuleTypes[attr.NamedEvent] = ruleType;

foreach (var eventId in attr.EventIds) {
var key = (eventId, attr.LogName);
if (!_eventHandlers.ContainsKey(key)) {
_eventHandlers[key] = new List<Type>();
if (!_reflectionHandlers.ContainsKey(key)) {
_reflectionHandlers[key] = new List<Type>();
}
_eventHandlers[key].Add(ruleType);
_reflectionHandlers[key].Add(ruleType);
}
}
}
Expand All @@ -243,27 +246,59 @@ private static void RegisterEventRuleType(Type ruleType) {
/// Gets all event rule types that can handle the given event.
/// </summary>
public static List<Type> GetEventHandlers(int eventId, string logName) {
EnsureInitialized();
var key = (eventId, logName);
return _eventHandlers.TryGetValue(key, out var handlers) ? handlers : new List<Type>();
var mode = _discoveryMode;
EnsureInitialized();

if (mode == EventRuleDiscoveryMode.ExplicitOnly) {
return _explicitHandlers.TryGetValue(key, out var explicitHandlers) ? explicitHandlers : new List<Type>();
}
if (mode == EventRuleDiscoveryMode.Reflection) {
return _reflectionHandlers.TryGetValue(key, out var reflectionHandlers) ? reflectionHandlers : new List<Type>();
}

var combined = new List<Type>();
if (_explicitHandlers.TryGetValue(key, out var explicitList)) {
combined.AddRange(explicitList);
}
if (_reflectionHandlers.TryGetValue(key, out var reflectionList)) {
foreach (var t in reflectionList) {
if (!combined.Contains(t)) {
combined.Add(t);
}
}
}
return combined;
}

/// <summary>
/// Gets the event rule type for a named event.
/// </summary>
public static Type? GetEventRuleType(NamedEvents namedEvent) {
var mode = _discoveryMode;
EnsureInitialized();
return _eventRuleTypes.TryGetValue(namedEvent, out var type) ? type : null;

if (mode == EventRuleDiscoveryMode.ExplicitOnly) {
return _explicitRuleTypes.TryGetValue(namedEvent, out var explicitType) ? explicitType : null;
}
if (mode == EventRuleDiscoveryMode.Reflection) {
return _reflectionRuleTypes.TryGetValue(namedEvent, out var reflectionType) ? reflectionType : null;
}

return _explicitRuleTypes.TryGetValue(namedEvent, out var type) ? type
: _reflectionRuleTypes.TryGetValue(namedEvent, out var reflection) ? reflection
: null;
}

/// <summary>
/// Creates an event rule instance from an <see cref="EventObject"/>.
/// </summary>
public static EventObjectSlim? CreateEventRule(EventObject eventObject, List<NamedEvents> targetNamedEvents) {
var mode = _discoveryMode;
EnsureInitialized();

foreach (var namedEvent in targetNamedEvents) {
if (_ruleFactories.TryGetValue(namedEvent, out var reg)) {
if (mode != EventRuleDiscoveryMode.Reflection && _ruleFactories.TryGetValue(namedEvent, out var reg)) {
try {
if (reg.CanHandle != null && !reg.CanHandle(eventObject)) {
continue;
Expand All @@ -282,8 +317,11 @@ public static List<Type> GetEventHandlers(int eventId, string logName) {
}
}

var ruleType = GetEventRuleType(namedEvent);
if (ruleType == null) {
if (mode == EventRuleDiscoveryMode.ExplicitOnly) {
continue;
}

if (!_reflectionRuleTypes.TryGetValue(namedEvent, out var ruleType) || ruleType == null) {
continue;
}

Expand Down Expand Up @@ -333,12 +371,13 @@ private static NamedEvents GetNamedEventForType(Type type) {
/// Gets event IDs and log name for named events using rule classes.
/// </summary>
public static Dictionary<string, HashSet<int>> GetEventInfoForNamedEvents(List<NamedEvents> namedEvents) {
var mode = _discoveryMode;
EnsureInitialized();

var eventInfoDict = new Dictionary<string, HashSet<int>>();

foreach (var namedEvent in namedEvents) {
if (_ruleFactories.TryGetValue(namedEvent, out var reg)) {
if (mode != EventRuleDiscoveryMode.Reflection && _ruleFactories.TryGetValue(namedEvent, out var reg)) {
if (!eventInfoDict.TryGetValue(reg.LogName, out var idSet)) {
idSet = new HashSet<int>();
eventInfoDict[reg.LogName] = idSet;
Expand All @@ -349,8 +388,11 @@ public static Dictionary<string, HashSet<int>> GetEventInfoForNamedEvents(List<N
continue;
}

var ruleType = GetEventRuleType(namedEvent);
if (ruleType == null) {
if (mode == EventRuleDiscoveryMode.ExplicitOnly) {
continue;
}

if (!_reflectionRuleTypes.TryGetValue(namedEvent, out var ruleType) || ruleType == null) {
continue;
}

Expand Down
Loading