代码之家  ›  专栏  ›  技术社区  ›  Junior

如何使用c#检查类是否实现并与泛型接口?

c#
  •  2
  • Junior  · 技术社区  · 8 年前

    我有以下界面

    public interface IHandleSuccess<T> where T : Event
    {
        void Finished(T _event, Listener<T> listener);
    }
    

    下一节课呢

    public abstract class Listener<T> where T : Event
    {
        public abstract void Handle(T _event);
    }
    

    下面的类 Listener<T> 和工具 IHandleSuccess<T>

    public class SendConfirmationEmail : Listener<UserWasUpdated>, IHandleSuccess<UserWasUpdated>
    {
        public override void Handle(UserWasUpdated _event)
        {
            // ...
        }
    
        public void Finished(UserWasUpdated _event, Listener<UserWasUpdated> listener)
        {
            // ...
        }
    }
    

    最后,另一个侦听器 侦听器<T> IHandleSuccess<T>

    public class ScheduleOriantation: Listener<UserWasUpdated>
    {
        public override void Handle(UserWasUpdated _event)
        {
            // ...
        }
    }
    

    我的 SendConfirmationEmail 获取类已注册到我的 IoC 应用程序启动时的容器。

    我想检查解析的实例是否实现了契约。如果有,我想打电话给 Finished

    public void Announce<T>(T _event) where T : Event
    {
        IEnumerable<Listener<T>> listeners = Container.ResolveAll<Listener<T>>()
    
        foreach (var listener in listeners)
        {
            try
            {
                listener.Handle(_event);
    
                if (listener is IHandleSuccess<> _listener)
                {
                    _listener.Finished(_event, listener);
                }
            }
            catch (Exception e)
            {
                // ...
            }
        }
    }
    

    然而,这条线 IHandleSuccess<> 给我一个错误

    意外使用了未绑定的泛型名称

    因为泛型参数总是扩展 Event 类,我还尝试将代码更改为

    listener.Handle(_event);
    
    if (listener is IHandleSuccess<Event> _listener)
    {
        _listener.Finished(_event, listener);
    }
    

    但是 _listener.Finished(_event, listener) 给我以下错误

    第二个参数不能从 侦听器<T> 到 Listener<Event>

    如何正确修复此错误?

    3 回复  |  直到 8 年前
        1
  •  5
  •   Scott Chamberlain    8 年前

    你已经知道 IHandleSuccess<> 会的,会的 T 因为你声明你会收到 Listener<T> 是请求中的。

    public void Announce<T>(T _event) where T : Event
    {
        IEnumerable<Listener<T>> listeners = Container.ResolveAll<Listener<T>>()
    
        foreach (var listener in listeners)
        {
            try
            {
                listener.Handle(_event);
    
                if (listener is IHandleSuccess<T> _listener)
                {
                    _listener.Finished(_event, listener);
                }
            }
            catch (Exception e)
            {
                // ...
            }
        }
    }
    

    下面是一个示例,如果Announce不是泛型的

    public void Announce(Foo _event)
    {
        IEnumerable<Listener<Foo>> listeners = Container.ResolveAll<Listener<Foo>>()
    
        foreach (var listener in listeners)
        {
            try
            {
                listener.Handle(_event);
    
                if (listener is IHandleSuccess<Foo> _listener)
                {
                    _listener.Finished(_event, listener);
                }
            }
            catch (Exception e)
            {
                // ...
            }
        }
    }
    
        2
  •  5
  •   Boudin    8 年前

    这个代码不起作用

    var cls = new SendConfirmationEmail();
    
    if (cls is IHandleSuccess<Event> _cls)
    {
        _cls.Finished(_event, cls);
    }
    

    cls 属于类型 SendConfirmationEmail() 哪个实现了 Listener<UserWasUpdated> 鉴于 _cls 铸造为 IHandleSuccess<Event> . _cls.Finished() 需要一个参数 listener 类型 Listener<Event> ,不是

    你的功能有什么用 Finished(UserWasUpdated _event, Listener<UserWasUpdated> listener) ? 看看你使用它的方式,你可以去掉参数c 听众 并使用引用当前侦听器 this :

    public interface IHandleSuccess<T> where T : Event
    {
        void Finished(T _event);
    }
    

    public class SendConfirmationEmail : Listener<UserWasUpdated>, IHandleSuccess<UserWasUpdated>
    {
        public override void Handle(UserWasUpdated _event)
        {
            // ...
        }
    
        public void Finished(UserWasUpdated _event)
        {
            // Call whatever function on your object
            this.Cleanup()
        }
    }
    

    要回答第一个问题,这不起作用,因为泛型的每次使用都是不同的类型:

    var cls = new SendConfirmationEmail();
    
    if (cls is IHandleSuccess<> _cls)
    {
        // _event and cls types can't be resolved at compilation time here:
        _cls.Finished(_event, cls);
    }
    

    如果您想做到这一点,您需要使您的接口非泛型。 如果 _event 对象被您的对象所知 cls公司 事先,您可以将其存储并在 Finished()

    接口:

    public interface IHandleSuccess
    {
        void Finished();
    }
    

    public class SendConfirmationEmail : Listener<UserWasUpdated>, IHandleSuccess
    {
        private _Event = null;
    
        public override void Handle(UserWasUpdated _event)
        {
            // Store _event
            _Event = _event;
        }
    
        public void Finished()
        {
            // Call whatever function on your object
            this.Cleanup()
    
            // Call whatever is needed on _event
            _Event?.Cleanup();
        }
    }
    

    然后您可以执行以下操作:

    var cls = new SendConfirmationEmail();
    
    if (cls is IHandleSuccess _cls)
    {
        _cls.Finished();
    }