我有以下界面
public interface IHandleSuccess<T> where T : Event
{
void Finished(T _event, Listener<T> listener);
}
Run Code Online (Sandbox Code Playgroud)
以下课程
public abstract class Listener<T> where T : Event
{
public abstract void Handle(T _event);
}
Run Code Online (Sandbox Code Playgroud)
以下类扩展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)
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
最后,另一个扩展Listener<T>但未实现的侦听器IHandleSuccess<T>
public class ScheduleOriantation: Listener<UserWasUpdated>
{
public override void Handle(UserWasUpdated _event)
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序启动时,我的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)
{
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这条线IHandleSuccess<>给了我一个错误
意外使用未绑定的通用名称
由于泛型参数将始终扩展Event类,我还尝试将代码更改为以下内容
listener.Handle(_event);
if (listener is IHandleSuccess<Event> _listener)
{
_listener.Finished(_event, listener);
}
Run Code Online (Sandbox Code Playgroud)
但是_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)
{
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个例子,如果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)
{
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
此代码不起作用
var cls = new SendConfirmationEmail();
if (cls is IHandleSuccess<Event> _cls)
{
_cls.Finished(_event, cls);
}
Run Code Online (Sandbox Code Playgroud)
因为cls是SendConfirmationEmail()实现的类型Listener<UserWasUpdated>而是_cls被铸造的类型IHandleSuccess<Event>.该函数需要_cls.Finished()一个listener类型的参数Listener<Event>,而不是Listener<UserWasUpdated>
你的功能有Finished(UserWasUpdated _event, Listener<UserWasUpdated> listener)什么用?查看您使用它的方式,您可以删除参数listenerc并使用this以下内容引用当前侦听器:
所以界面看起来像这样:
public interface IHandleSuccess<T> where T : Event
{
void Finished(T _event);
}
Run Code Online (Sandbox Code Playgroud)
和这样的实现:
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()
}
}
Run Code Online (Sandbox Code Playgroud)
要回答第一个问题,这不起作用,因为泛型的每次使用都是不同的类型:
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);
}
Run Code Online (Sandbox Code Playgroud)
如果您希望能够这样做,则需要使界面非通用.如果_event对象cls事先为您的对象所知,您可以将其存储并在Finished()调用中使用它,如下所示:
接口:
public interface IHandleSuccess
{
void Finished();
}
Run Code Online (Sandbox Code Playgroud)
和这样的实现:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
var cls = new SendConfirmationEmail();
if (cls is IHandleSuccess _cls)
{
_cls.Finished();
}
Run Code Online (Sandbox Code Playgroud)