繁体   English   中英

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

[英]how to check if a class implements and interface with a generic using c#?

我有以下界面

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)
    {
        // ...
    }
}

最后,另一个监听Listener<T>扩展了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)给了我以下错误

第二个参数无法从Listener<T>转换为Listener<Event>

我该如何正确修复此错误?

您已经知道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)
        {
            // ...
        }
    }
}

此代码不起作用

var cls = new SendConfirmationEmail();

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

因为cls的类型为SendConfirmationEmail() ,它实现了Listener<UserWasUpdated>_cls则被转换为IHandleSuccess<Event> 函数_cls.Finished()期望一个Listener<Event>类型的参数listener Listener<Event> ,而不是Listener<UserWasUpdated>

你的函数有什么用? Finished(UserWasUpdated _event, Listener<UserWasUpdated> listener) 查看您使用它的方式,您可以删除parameterc listener并使用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);
}

如果您希望能够这样做,则需要使界面非通用。 如果事先已知对象cls _event对象,则可以将其存储并在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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM