在抽象类中触发实体具体事件的实现方案咨询
可行实现方案
方案一:泛型自约束的ToggleEntity
将ToggleEntity改为泛型抽象类,通过自约束让基类明确具体实体类型,从而直接在通用方法中创建对应事件。
代码调整
修改基类ToggleEntity:
public abstract class ToggleEntity<T> : Entity where T : ToggleEntity<T> { public DateTime? DateDeactivated { get; set; } public virtual void Activate() { DateDeactivated = null; // 构建对应实体的激活事件类型 var eventGenericType = typeof(ActivatedEntityEvent<>); var concreteEventType = eventGenericType.MakeGenericType(typeof(T)); // 创建事件实例并设置触发实体 var activatedEvent = (EntityEvent)Activator.CreateInstance(concreteEventType); activatedEvent.RaisingEntity = this; RaiseEvent(activatedEvent); } public virtual void Deactivate() { DateDeactivated = DateTime.Now; // 同理处理停用事件 var eventGenericType = typeof(DeactivatedEntityEvent<>); var concreteEventType = eventGenericType.MakeGenericType(typeof(T)); var deactivatedEvent = (EntityEvent)Activator.CreateInstance(concreteEventType); deactivatedEvent.RaisingEntity = this; RaiseEvent(deactivatedEvent); } }
实体子类继承时指定自身类型:
public class Foo : ToggleEntity<Foo> { } public class Bar : ToggleEntity<Bar> { }
事件类保持原有定义即可:
public abstract class ActivatedEntityEvent<T> : EntityEvent where T : ToggleEntity<T> { } public class FooActivatedEvent : ActivatedEntityEvent<Foo> { } public class BarActivatedEvent : ActivatedEntityEvent<Bar> { }
核心逻辑
泛型自约束where T : ToggleEntity<T>确保T是当前实体的具体类型,基类通过typeof(T)获取实体类型,结合反射创建对应泛型事件实例,无需子类重写方法即可自动触发专属事件。
方案二:反射查找+缓存(不修改原有继承结构)
如果不想变更ToggleEntity的非泛型结构,可通过反射获取当前实例的具体类型,提前缓存实体与事件的映射关系,实现自动触发。
代码调整
修改ToggleEntity类:
public abstract class ToggleEntity : Entity { // 缓存实体类型到对应事件类型的映射 private static readonly Dictionary<Type, Type> _activatedEventMap = new(); private static readonly Dictionary<Type, Type> _deactivatedEventMap = new(); static ToggleEntity() { // 初始化激活事件映射 var assembly = Assembly.GetExecutingAssembly(); var activatedEvents = assembly.GetTypes() .Where(t => !t.IsAbstract && t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(ActivatedEntityEvent<>)); foreach (var eventType in activatedEvents) { var entityType = eventType.BaseType.GetGenericArguments()[0]; _activatedEventMap[entityType] = eventType; } // 初始化停用事件映射 var deactivatedEvents = assembly.GetTypes() .Where(t => !t.IsAbstract && t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(DeactivatedEntityEvent<>)); foreach (var eventType in deactivatedEvents) { var entityType = eventType.BaseType.GetGenericArguments()[0]; _deactivatedEventMap[entityType] = eventType; } } public DateTime? DateDeactivated { get; set; } public virtual void Activate() { DateDeactivated = null; var entityType = GetType(); if (_activatedEventMap.TryGetValue(entityType, out var eventType)) { var activatedEvent = (EntityEvent)Activator.CreateInstance(eventType); activatedEvent.RaisingEntity = this; RaiseEvent(activatedEvent); } } public virtual void Deactivate() { DateDeactivated = DateTime.Now; var entityType = GetType(); if (_deactivatedEventMap.TryGetValue(entityType, out var eventType)) { var deactivatedEvent = (EntityEvent)Activator.CreateInstance(eventType); deactivatedEvent.RaisingEntity = this; RaiseEvent(deactivatedEvent); } } }
核心逻辑
- 静态构造函数仅执行一次,遍历程序集获取所有事件类型并缓存到字典中
- 调用
Activate/Deactivate时,通过GetType()获取当前实例的具体类型,直接从字典中查找对应事件类型 - 创建事件实例并设置触发实体后,调用
RaiseEvent完成触发
内容的提问来源于stack exchange,提问作者JGillardCCG
相关产品推荐
相关产品推荐

