泛型方法的可重用非泛型方法 [英] Reusable non generic method for generic methods
问题描述
我有以下基本接口:
public interface IHandler {
void Handle(IMessage message);
}
以及继承基本接口的通用接口
public interface IHandler< TMessage> :IHandler其中TMessage:IMessage {
void Handle(TMessage message);
}
我的类可以实现接口 IHandler< TMessage>
多次。 IMessage
是消息的基本接口,在这里不重要。
public class ExampleHandler:IHandler< ExampleMessage> ;, IHandler< OtherExampleMessag> {
void IHandler.Handle(IMessage message){
ExampleMessage example = message作为ExampleMessage;
if(example!= null){
Handle(example);
}
else {
OtherExampleMessage otherExample = message作为OtherExampleMessage;
if(otherExample!= null){
Handle(otherExample);
}
}
public void Handle(ExampleMessage){
// handle handle message;
}
public void Handle(OtherExampleMessage){
// handle handle message;
困扰我的是我必须实现处理(IMessage)
方法,在我看来它的许多冗余代码,并且我必须在每次执行新的 IHandler< TMessage>
接口在我的类。
我正在寻找的是更通用的方式来实现 Handle (IMessage)
方法(也许在处理程序的基类中),但我目前坚持如何做到这一点。
动态
关键字将重载解析移至DLR: void IHandler.Handle(IMessage消息)
{
dynamic d = message;
手柄(d);
$ / code>
请注意,这会在运行时失败,出现 RuntimeBinderException
如果传入的消息对您的类无效。
为避免此异常,您可以为所有未知消息类型添加处理程序:
private void Handle(object unknownMessage)
{
//在这里处理未知的消息类型。
$ p $要实现 IHandler.Handle
在基类中,您需要做更多的工作:
public class BaseHandler:IHandler
{
void IHandler.Handle(IMessage message)
{
dynamic d = message;
手柄(d);
}
private void Handle< TMessage>(TMessage message)其中TMessage:IMessage
{
var handler = this作为IHandler< TMessage>;
if(handler == null)
HandleUnknownMessage(message);
else
handler.Handle(message);
}
protected virtual void HandleUnknownMessage(IMessage unknownMessage)
{
//在这里处理未知的消息类型。
code
$ b 你的特定处理程序看起来像这样:
public class ExampleHandler:BaseHandler,
IHandler< ExampleMessage> ;,
IHandler< OtherExampleMessage>
{
public void Handle(ExampleMessage message)
{
// Handle ExampleMessage
}
$ b $ public void Handle(OtherExampleMessage message)
{
//在这里处理OtherExampleMessage
}
}
这段代码现在可以像这样工作:
- DLR调用通用的
BaseHandler.Handle< TMessage> / code>方法与真正的消息类型,即 TMessage
不会是 IMessage
,但具体的消息类例如 ExampleMessage
。
- 在这个Geneirc处理程序方法中,基类尝试将自身大小写为特定消息的处理程序。 li>
- 如果不成功,它会调用
HandleUnknownMessage
来处理未知的消息类型。转换成功,它在特定的消息处理程序上调用 Handle
方法,有效地将调用委托给具体的Handl er实现。
I have the following base interface
public interface IHandler{
void Handle(IMessage message);
}
and an generic interface inheriting the base interface
public interface IHandler<TMessage> : IHandler where TMessage : IMessage{
void Handle(TMessage message);
}
My classes can implement the interface IHandler<TMessage>
mutiple times. IMessage
is an base interface for messages and isn´t relevant here. Currently i´m implementing the interfaces as follows.
public class ExampleHandler : IHandler<ExampleMessage>, IHandler<OtherExampleMessag>{
void IHandler.Handle(IMessage message){
ExampleMessage example = message as ExampleMessage;
if (example != null) {
Handle(example);
}
else {
OtherExampleMessage otherExample = message as OtherExampleMessage;
if (otherExample != null) {
Handle(otherExample);
}
}
public void Handle(ExampleMessage) {
//handle message;
}
public void Handle(OtherExampleMessage) {
//handle message;
}
}
What bothers me is the way i have to implement the Handle(IMessage)
method, cause in my opinion its many redundant code, and i have to extend the method each time when i implement a new IHandler<TMessage>
interface on my class.
What i´m looking for is a more generic way to implement the Handle(IMessage)
method (maybe in a base class for Handlers), but i´m currently stuck how to do that.
解决方案 You can use the new dynamic
keyword to move the overload resolution to the DLR:
void IHandler.Handle(IMessage message)
{
dynamic d = message;
Handle(d);
}
Please note that this will fail at runtime with a RuntimeBinderException
if the message passed in is not valid for your class.
To avoid this exception you can add a Handler for all unknown message types:
private void Handle(object unknownMessage)
{
// Handle unknown message types here.
}
To implement IHandler.Handle
in a base class, you need to do a little bit more work:
public class BaseHandler : IHandler
{
void IHandler.Handle(IMessage message)
{
dynamic d = message;
Handle(d);
}
private void Handle<TMessage>(TMessage message) where TMessage : IMessage
{
var handler = this as IHandler<TMessage>;
if(handler == null)
HandleUnknownMessage(message);
else
handler.Handle(message);
}
protected virtual void HandleUnknownMessage(IMessage unknownMessage)
{
// Handle unknown message types here.
}
}
Your specific handler would than look like this:
public class ExampleHandler : BaseHandler,
IHandler<ExampleMessage>,
IHandler<OtherExampleMessage>
{
public void Handle(ExampleMessage message)
{
// handle ExampleMessage here
}
public void Handle(OtherExampleMessage message)
{
// handle OtherExampleMessage here
}
}
This code now works like this:
- The DLR calls the generic
BaseHandler.Handle<TMessage>
method with the real message type, i.e. TMessage
will not be IMessage
but the concrete message class like ExampleMessage
.
- In this geneirc handler method, the base class tries to case itself to a handler for the specific message.
- If that is not successful, it calls
HandleUnknownMessage
to handle the unknown message type.
- If the cast is successful, it calls the
Handle
method on the specific message handler, effectifly delegating the call to the concrete Handler implementation.
这篇关于泛型方法的可重用非泛型方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!