자세 한 설명 c\#이벤트 버스

9826 단어 c#이벤트 버스
간단 한 소개
이벤트 버스 는 게시-구독 모드 에 대한 일종 의 실현 으로 집중 식 이벤트 처리 체제 로 서로 다른 구성 요소 간 에 서로 통신 할 수 있 고 서로 의존 하지 않 아 도 되 며 결합 을 해제 하 는 목적 을 달성 할 수 있 습 니 다.
이벤트 버스 구현
EventBus 는 이벤트 사전 을 유지 합 니 다.게시 자,구독 자 는 이벤트 버스 에서 이벤트 인 스 턴 스 를 가 져 오고 게시,구독 작업 을 수행 합 니 다.이벤트 인 스 턴 스 는 이벤트 처리 프로그램 을 유지 하고 실행 합 니 다.절 차 는 다음 과 같다.

이벤트 기본 클래스 정의
이벤트 인 스 턴 스 는 이벤트 버스 에 등록 하고 기본 클래스 를 정의 하여 이벤트 버스 를 관리 해 야 합 니 다.코드 는 다음 과 같 습 니 다.

/// <summary>
///     
/// </summary>
public abstract class EventBase{ }
이벤트 인 스 턴 스 는 등 록 된 이벤트 처리 프로그램 을 관리 하고 실행 해 야 합 니 다.서로 다른 이벤트 매개 변수 에 적응 하기 위해 서 는 일반적인 파 라 메 터 를 사용 할 수 없습니다.코드 는 다음 과 같 습 니 다:

/// <summary>
///     
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class PubSubEvent<T> : EventBase where T : EventArgs
{
    protected static readonly object locker = new object();

    protected readonly List<Action<object, T>> subscriptions = new List<Action<object, T>>();

    public void Subscribe(Action<object, T> eventHandler)
    {
        lock (locker)
        {
            if (!subscriptions.Contains(eventHandler))
            {
                subscriptions.Add(eventHandler);
            }
        }
    }

    public void Unsubscribe(Action<object, T> eventHandler)
    {
        lock (locker)
        {
            if (subscriptions.Contains(eventHandler))
            {
                subscriptions.Remove(eventHandler);
            }
        }
    }

    public virtual void Publish(object sender, T eventArgs)
    {
        lock (locker)
        {
            for (int i = 0; i < subscriptions.Count; i++)
            {
                subscriptions[i](sender, eventArgs);
            }
        }
    }
}
이벤트 매개 변수 기본 클래스 정의
이벤트 매개 변수 기본 클래스 는 EventArgs 를 계승 하고 일반적인 매개 변 수 를 사용 하여 서로 다른 매개 변수 유형 에 적응 하 며 이러한 예화 가 허용 되 지 않 습 니 다.코드 는 다음 과 같 습 니 다:

/// <summary>
///       
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class PubSubEventArgs<T> : EventArgs
{
    public T Value { get; set; }
}
정의 EventBus
EventBus 는 이벤트 인 스 턴 스 관리 만 제공 하고 구체 적 인 이벤트 처리 프로그램의 실행 은 이벤트 인 스 턴 스 가 스스로 책임 집 니 다.사용 편 의 를 위해 구조 함 수 는 자동 으로 이벤트 등록 기능 이 있 으 며,여러 프로그램 집합 이 있 을 때 bug 가 있 을 수 있 습 니 다.코드 는 다음 과 같 습 니 다:

/// <summary>
///     
/// </summary>
class EventBus
{
    private static EventBus _default;
    private static readonly object locker = new object();
    private Dictionary<Type, EventBase> eventDic = new Dictionary<Type, EventBase>();
    
    /// <summary>
    ///         ,        
    /// </summary>
    public static EventBus Default
    {
        get
        {
            if (_default == null)
            {
                lock (locker)
                {
                    //             ,      
                    if (_default == null)
                    {
                        _default = new EventBus();                            
                    }
                }
            }
            return _default;
        }
    }

    /// <summary>
    ///     ,    EventBase      
    /// </summary>
    public EventBus() 
    {
        Type type = typeof(EventBase);
        Type typePubSub = typeof(PubSubEvent<>);
        Assembly assembly = Assembly.GetAssembly(type);
        List<Type> typeList = assembly.GetTypes()
            .Where(t => t != type && t != typePubSub && type.IsAssignableFrom(t))
            .ToList();
        foreach (var item in typeList)
        {
            EventBase eventBase = (EventBase)assembly.CreateInstance(item.FullName);
            eventDic.Add(item, eventBase);
        }
    }
    
    /// <summary>
    ///       
    /// </summary>
    /// <typeparam name="TEvent">    </typeparam>
    /// <returns></returns>
    public TEvent GetEvent<TEvent>() where TEvent : EventBase
    {
        return (TEvent)eventDic[typeof(TEvent)];
    }

    /// <summary>
    ///       
    /// </summary>
    /// <typeparam name="TEvent"></typeparam>
    public void AddEvent<TEvent>() where TEvent : EventBase ,new()
    {
        lock (locker) 
        {
            Type type = typeof(TEvent);
            if (!eventDic.ContainsKey(type))
            {
                eventDic.Add(type, new TEvent());                    
            }
        }
    }

    /// <summary>
    ///       
    /// </summary>
    /// <typeparam name="TEvent"></typeparam>
    public void RemoveEvent<TEvent>() where TEvent : EventBase, new()
    {
        lock (locker)
        {
            Type type = typeof(TEvent);
            if (eventDic.ContainsKey(type))
            {
                eventDic.Remove(type);
            }
        }
    }
}
이벤트 버스 사용
이벤트 및 이벤트 매개 변수
이벤트 버스 를 사용 하기 전에 이벤트 와 이벤트 파 라 메 터 를 정의 해 야 합 니 다.사용 할 때 게시 자,구독 자 도 이벤트 유형 과 이벤트 매개 변수 유형 을 알 아야 합 니 다.코드 는 다음 과 같 습 니 다:

/// <summary>
///       -TestAEvent,         
/// </summary>
public class TestAEvent: PubSubEvent<TestAEventArgs> 
{
    public override void Publish(object sender, TestAEventArgs eventArgs)
    {
        lock (locker)
        {
            for (int i = 0; i < subscriptions.Count; i++)
            {
                var action= subscriptions[i];
                Task.Run(() => action(sender, eventArgs));
            }
        }
    }
}
/// <summary>
///         -TestAEventArgs
/// </summary>
public class TestAEventArgs : PubSubEventArgs<string> { }


/// <summary>
///       -TestBEvent
/// </summary>
public class TestBEvent : PubSubEvent<TestBEventArgs> { }
/// <summary>
///         -TestBEventArgs
/// </summary>
public class TestBEventArgs : PubSubEventArgs<int> { }
주:TestAEvent 에 서 는 이벤트 발표 논 리 를 재 작성 하여 모든 이벤트 가 작업 에서 실 행 됩 니 다.
게시 자 정의
게시 자 는 이벤트 버스 를 통 해 이벤트 인 스 턴 스 를 가 져 옵 니 다.인 스 턴 스 에서 이 벤트 를 발표 합 니 다.코드 는 다음 과 같 습 니 다.

class Publisher
{        
    public void PublishTeatAEvent(string value) 
    {
        EventBus.Default.GetEvent<TestAEvent>().Publish(this, new TestAEventArgs() { Value=value});
    }

    public void PublishTeatBEvent(int value)
    {
        EventBus.Default.GetEvent<TestBEvent>().Publish(this, new TestBEventArgs() { Value = value });
    }
}
구독 자 정의
구독 자 는 이벤트 버스 를 통 해 이벤트 인 스 턴 스 를 가 져 옵 니 다.인 스 턴 스 에서 이 벤트 를 구독 합 니 다.코드 는 다음 과 같 습 니 다.

class ScbscriberA
{
    public string Name { get; set; }

    public ScbscriberA(string name)
    {
        Name = name;
        EventBus.Default.GetEvent<TestAEvent>().Subscribe(TeatAEventHandler);
    }

    public void TeatAEventHandler(object sender, TestAEventArgs e)
    {
        Console.WriteLine(Name+":"+e.Value);
    }
}

class ScbscriberB
{
    public string Name { get; set; }

    public ScbscriberB(string name)
    {
        Name = name;
        EventBus.Default.GetEvent<TestBEvent>().Subscribe(TeatBEventHandler);
    }

    public void Unsubscribe_TeatBEvent() 
    {
        EventBus.Default.GetEvent<TestBEvent>().Unsubscribe(TeatBEventHandler);
    }

    public void TeatBEventHandler(object sender, TestBEventArgs e)
    {
        Console.WriteLine(Name + ":" + e.Value);
    }
}
실제 사용
코드 는 다음 과 같 습 니 다:

class Program
{
    static void Main(string[] args)
    {
        Publisher publisher = new Publisher();
        ScbscriberA scbscriberA = new ScbscriberA("scbscriberA");
        ScbscriberB scbscriberB1 = new ScbscriberB("scbscriberB1");
        ScbscriberB scbscriberB2 = new ScbscriberB("scbscriberB2");
        publisher.PublishTeatAEvent("test");
        publisher.PublishTeatBEvent(123);

        scbscriberB2.Unsubscribe_TeatBEvent();
        publisher.PublishTeatBEvent(12345);

        Console.ReadKey();           
    }    
}
실행 결과:
scbscriberB1:123
scbscriberB2:123
scbscriberA:test
scbscriberB1:12345
총결산
이 이벤트 버스 는 기본 기능 만 제공 하고 이 루어 진 게시 자 와 구독 자의 결합 을 해제 하 며 게시 자,구독 자 는 이벤트 에 만 의존 하고 서로 의존 하지 않 습 니 다.
제 가 사건 버스 에 대한 이해 가 아직 부족 하 다 고 생각 합 니 다.여러분 이 토론 하 시 는 것 을 환영 합 니 다!
이상 은 c\#이벤트 버스 의 상세 한 내용 입 니 다.c\#이벤트 버스 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기