Collecting common handlers - is it possible?

Using generics, is it possible to have a common set defined as a base type and assign subtype instances? I have a simple code example below that emphasizes my thinking and the line that causes the compiler error. I know that I can create an IEventHandler token interface and force my common event handlers to inherit. This would allow me to store generic types in the IList collection, but it seems less ideal. Is there a way similar to the code that I have below?

using System;
using System.Collections.Generic;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            IEventHandler<SomeEvent1> handler1 = new SomeEvent1Handler();
            IEventHandler<SomeEvent2> handler2 = new SomeEvent2Handler();


            IList<IEventHandler<IEvent>> handlers = new List<IEventHandler<IEvent>>();
            // COMPILE ERROR - is this possible?
            handlers.Add(new SomeEvent1Handler());
        }

        public interface IEvent {

        }

        public interface IEventHandler<in TEvent> where TEvent : IEvent 
        {
            void Handle(TEvent someEvent);
        }

        public class SomeEvent1 : IEvent {
        }
        public class SomeEvent2 : IEvent {
        }

        public class SomeEvent1Handler : IEventHandler<SomeEvent1>
        {
            public void Handle(SomeEvent1 someEvent)
            {
                throw new NotImplementedException();
            }
        }

        public class SomeEvent2Handler : IEventHandler<SomeEvent2>
        {
            public void Handle(SomeEvent2 someEvent)
            {
                throw new NotImplementedException();
            }
        }
    }

}
+4
source share
2 answers

Using generics is it possible for a generic set to be defined as a base type and assign subtype instances?

, , IEventHandler<out TEvent>, in.

, ,

    public static void Main(string[] args)
    {
        IList<IEventHandler<IEvent>> handlers = new List<IEventHandler<IEvent>>();
        handlers.Add(new SomeEvent1Handler()); //Magicly works
        IEventHandler<IEvent> handler = handlers[0];
        handler.Handle(new SomeEvent2());
    }

handler , IEvent Handle. , SomeEvent1Handler SomeEvent2 public void Handle(SomeEvent1 someEvent).

, IEvent, , , , , , .

using System;
using System.Collections.Generic;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            IEventHandler<SomeEvent1> handler1 = new SomeEvent1Handler();
            IEventHandler<SomeEvent2> handler2 = new SomeEvent2Handler();


            IList<IEventHandler> handlers = new List<IEventHandler>();

            handlers.Add(new SomeEvent1Handler());
        }

        public interface IEvent {

        }

        public interface IEventHandler 
        {
            void Handle(IEvent someEvent);
        }

        public class SomeEvent1 : IEvent {
        }
        public class SomeEvent2 : IEvent {
        }

        public class SomeEvent1Handler : IEventHandler
        {
            public void Handle(IEvent someEvent)
            {
                var event = someEvent as SomeEvent1;
                if(event == null)
                    return;

                //Do stuff here.
            }
        }

        public class SomeEvent2Handler : IEventHandler
        {
            public void Handle(IEvent someEvent)
            {
                var event = someEvent as SomeEvent2;
                if(event == null)
                    return;

                //Do stuff here.
            }
        }
    }

}
0

, - , :

var handlers = new List<IEventHandler<IEvent>> { new SomeEvent1Handler() };
handlers[0].Handle(new SomeEvent2());

, .

public class HandlerWrapper<T> : IEventHandler<IEvent>
{
    private readonly IEventHandler<T> inner;

    public HandlerWrapper(IEventHandler<T> inner)
    {
        this.inner = inner;
    }
    public void Handle(IEvent event)
    {
        if(event is T) { inner.handle((T)event); }
        else throw new ArgumentException("Unexpected event type");
    }
}

IList<EventHandler<IEvent>>, .

0

Source: https://habr.com/ru/post/1667030/


All Articles