Nopフレームワークでは、イベントメカニズムが多くの場所、特にキャッシュの更新で使用されていることがわかります。
このようなシナリオがある場合、顧客が登録した後、キャッシュを更新してから登録メールを送信します。通常の方法は次のとおりです。
void InsertCustomer()
{
1. 新增到数据库
2. 插入到缓存
3. 发送注册邮件
}
これで問題ありませんが、このようなコードは密に結合されます。登録後にクーポンを送信する別のアクションを追加する場合は、クーポンを送信するアクションを内部に追加して、ビジネスを安全にすることもできます。バインディングは新しい方法にしっかりと組み込まれていますが、Nopはそれをどのように行うのですか?
void Insert()
{
1. 新增到数据库
2. 发布一条新增消息
}
class CacheConsumer: IConsumer<EntityInsertedEvent<Customer>>
{
public void HandleEvent(EntityUpdatedEvent<Setting> eventMessage)
{
//新增缓存
}
}
class MailConsumer: IConsumer<EntityInsertedEvent<Customer>>
{
public void HandleEvent(EntityUpdatedEvent<Setting> eventMessage)
{
//发送邮件
}
}
実行プロセスを具体的に説明します。
- データを追加したら、メッセージマネージャーにメッセージを公開します
- 新しいメッセージをサブスクライブするすべての消費者がメッセージを受け取ります
- 消費者は、キャッシュの追加、電子メールの送信などの特定のイベントを実行します。
Nopの技術的な実装はもう少し複雑かもしれませんが、従来のRabbitMQやその他のサードパーティのメッセージキューを使用していませんが、Autofacの依存性注入を組み合わせて、この設計を巧みに実現しています。
- IEventPublisherイベント発行インターフェイス
- EventPublisherはIEventPublisherクラスを実装します。主な機能には、イベントの発行とサブスクライバーへの通知が含まれます
- IConsumer
コンシューマー(イベントサブスクライバー)インターフェイス - ISubscriptionServiceサブスクライバーインターフェイス、すべてのサブスクライバーを解決
- SubscriptionService固有の実装
次に、CategoryServiceを例にして、特定の実装クラスを見て、不要な詳細を削除します。
public virtual void InsertCategory(Category category)
{
_categoryRepository.Insert(category);
//发布一条消息
_eventPublisher.EntityInserted(category);
}
このメッセージをサブスクライブするPriceCacheEventConsumerのクラスには、次のコードがあります。
public partial class PriceCacheEventConsumer : IConsumer<EntityInsertedEvent<Category>>
{
public void HandleEvent(EntityInsertedEvent<Category> eventMessage)
{
_cacheManager.RemoveByPattern(NopCatalogDefaults.ProductCategoryIdsPatternCacheKey);
}
}
上記のコードは干渉係数を削除しました。このクラスはIConsumerから継承していることがわかります
次に、EventPublisherの機能を見てみましょう。
/// <summary>
/// 发布到消费者
/// </summary>
protected virtual void PublishToConsumer<T>(IConsumer<T> x, T eventMessage)
{
try
{
x.HandleEvent(eventMessage); //执行消费者订阅方法
}
catch (Exception exc)
{
}
}
/// <summary>
/// 发布事件,注意,是整个实现的核心
/// </summary>
public virtual void Publish<T>(T eventMessage)
{
//利用控制反转IOC技术,查找所有消费者类
var subscribers = _subscriptionService.GetSubscriptions<T>()
.Where(subscriber => PluginManager.FindPlugin(subscriber.GetType())?.Installed ?? true).ToList();
//调用PublishToConsumer,执行对应消费者类的方法,这个是关键
subscribers.ForEach(subscriber => PublishToConsumer(subscriber, eventMessage));
}
イベント発行サービス:SubscriptionService。このクラスはツールクラスであり、GetSubscriptionsタイプに基づいてコンシューマーを検索するメソッドを提供します
public IList<IConsumer<T>> GetSubscriptions<T>()
{
return EngineContext.Current.ResolveAll<IConsumer<T>>().ToList();
}
上記のクラスのEngineContext、Nopエンジンマネージャー、Currentは現在のエンジンを指し、ResolveAllはコンテナーからコンシューマークラスを取得します。特定のテクノロジーについてはAutofacを参照してください
要約すると:
- コード全体が分離を実現し、相互に依存しなくなります
- メッセージサブスクリプションを発行し、サードパーティのメッセージキューRabbitMQを直接使用しないため、個別の監視端末はありません
- 制御反転テクノロジーを使用して、消費者を見つける難しさを巧みに解決します。リフレクションを使用すると、パフォーマンスが低下します