如何在运行时指定泛型类型?
How to specify generic types at runtime?
我有一段代码是这样的:
var senders = new List<MessageSenderBase<object>>();
senders.Add(new MessageSender1<MessageType1>());
其中 MessageSender1<MessageType1>
派生自 MessageSenderBase<T>
而 MessageType1
是我定义的另一个 class。
现在第二行出现错误 CS1503 Argument 1: cannot convert from 'Demo.MessageSender.MessageSender1<Demo.MessageSender.MessageType1>' to 'Demo.MessageSender.MessageSenderBase<object>'
我该如何解决这个问题?
我的设计是 MessageSenderBase<T>
将放在我的库中,在 API 级别,用户可以派生他们自己的发件人 class 并指定他们想要的消息类型发送。我认为这会起作用,因为 object
是 MessageType1
的基数 class,而 MessageSenderBase<>
是 MessageSender1<>
的基数 class。
请帮忙,谢谢!
编辑 - 添加 MessageSenderBase
public class MessageSender1<MessageType1> : MessageSenderBase<MessageType1>
{
public override string Topic => "topic1";
public async override Task SendAsync()
{
//...
}
}
public abstract class MessageSenderBase<T>
{
public abstract string Topic { get;}
public T Deserialize(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}
public abstract Task SendAsync();
}
解决此问题的一种方法是添加一个新的 covariant 界面,其“形状”为 MessageSenderBase<T>
:
public interface IMessageSender<out T> {
string Topic { get; }
T Deserialize(string json);
Task SendAsync();
}
public abstract class MessageSenderBase<T>: IMessageSender<T>
{
public abstract string Topic { get;}
public T Deserialize(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}
public abstract Task SendAsync();
}
如果您现在将列表设为 List<IMessageSender<object>>
类型,则可以将 AnyMessageSender<AnythingReferenceType>
放入其中。
var senders = new List<IMessageSender<object>>();
senders.Add(new MessageSender1<MessageType1>());
请注意,如果 MessageSenderBase
有一个以 T
作为参数的方法(或者更一般地说,在“输入位置”有一个 T
),你不应该包括在 IMessageSender
中,因为如果这样做,从 MessageSender1<MessageType1>
转换为 IMessageSender<object>
不再安全。想象一下,如果您有:
public interface IMessageSender<out T> {
...
void Foo(T someT); // suppose this is implemented in MessageSender1
}
你可以做到:
var senders = new List<IMessageSender<object>>();
senders.Add(new MessageSender1<MessageType1>());
senders[0].Foo("abc"); // let's try giving a string to Foo
但是 senders[0]
是一个 MessageSender1<MessageType1>
对象。 MessageSender1<MessageType1>.Foo
只接受 MessageType1
个对象,不接受字符串!
我有一段代码是这样的:
var senders = new List<MessageSenderBase<object>>();
senders.Add(new MessageSender1<MessageType1>());
其中 MessageSender1<MessageType1>
派生自 MessageSenderBase<T>
而 MessageType1
是我定义的另一个 class。
现在第二行出现错误 CS1503 Argument 1: cannot convert from 'Demo.MessageSender.MessageSender1<Demo.MessageSender.MessageType1>' to 'Demo.MessageSender.MessageSenderBase<object>'
我该如何解决这个问题?
我的设计是 MessageSenderBase<T>
将放在我的库中,在 API 级别,用户可以派生他们自己的发件人 class 并指定他们想要的消息类型发送。我认为这会起作用,因为 object
是 MessageType1
的基数 class,而 MessageSenderBase<>
是 MessageSender1<>
的基数 class。
请帮忙,谢谢!
编辑 - 添加 MessageSenderBase
public class MessageSender1<MessageType1> : MessageSenderBase<MessageType1>
{
public override string Topic => "topic1";
public async override Task SendAsync()
{
//...
}
}
public abstract class MessageSenderBase<T>
{
public abstract string Topic { get;}
public T Deserialize(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}
public abstract Task SendAsync();
}
解决此问题的一种方法是添加一个新的 covariant 界面,其“形状”为 MessageSenderBase<T>
:
public interface IMessageSender<out T> {
string Topic { get; }
T Deserialize(string json);
Task SendAsync();
}
public abstract class MessageSenderBase<T>: IMessageSender<T>
{
public abstract string Topic { get;}
public T Deserialize(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}
public abstract Task SendAsync();
}
如果您现在将列表设为 List<IMessageSender<object>>
类型,则可以将 AnyMessageSender<AnythingReferenceType>
放入其中。
var senders = new List<IMessageSender<object>>();
senders.Add(new MessageSender1<MessageType1>());
请注意,如果 MessageSenderBase
有一个以 T
作为参数的方法(或者更一般地说,在“输入位置”有一个 T
),你不应该包括在 IMessageSender
中,因为如果这样做,从 MessageSender1<MessageType1>
转换为 IMessageSender<object>
不再安全。想象一下,如果您有:
public interface IMessageSender<out T> {
...
void Foo(T someT); // suppose this is implemented in MessageSender1
}
你可以做到:
var senders = new List<IMessageSender<object>>();
senders.Add(new MessageSender1<MessageType1>());
senders[0].Foo("abc"); // let's try giving a string to Foo
但是 senders[0]
是一个 MessageSender1<MessageType1>
对象。 MessageSender1<MessageType1>.Foo
只接受 MessageType1
个对象,不接受字符串!