【发布时间】:2021-03-31 12:46:33
【问题描述】:
根据以下对象定义:
public interface IMessage
{
Guid Identifier { get; set; }
}
public class Message : IMessage
{
public Guid Identifier { get; set; }
}
public interface IEventMessage<TPayload> : IMessage
{
TPayload Payload { get; set; }
}
public class EventMessage<TPayload> : Message, IEventMessage<TPayload>
{
public TPayload Payload { get; set; }
}
public interface ICommandMessage<TParameters> : IMessage
{
TParameters Parameters { get; set; }
}
public class CommandMessage<TParameters> : Message, ICommandMessage<TParameters>
{
public TPayload Payload { get; set; }
}
我想根据消息的类型过滤消息集合,而不考虑它们的通用类型
var messages = new List<IMessage>
{
new CommandMessage<string>() { Name = "Command Message String" },
new CommandMessage<int>() { Name = "Command Message Int" },
new EventMessage<string>() { Name = "Event Message String" },
new EventMessage<int>() { Name = "Event Message Int" }
};
var onlyStringCommandMessages = messages.OfType<CommandMessage<string>>(); // OK
var onlyIntCommandMessages = messages.OfType<CommandMessage<int>>(); // OK
var onlyCommandMessages = messages.OfType<CommandMessage<object>>(); // KO
var onlyCommandMessages2 = messages.OfType<CommandMessage<dynamic>>(); // KO
我尝试过其他技术,例如:
var onlyCommandMessages3 = messages.Where(x =>
x.GetType()
.GetInterfaces()
.Any(i => i.IsGenericType && (i.GetGenericTypeDefinition() == typeof(ICommandMessage<>)))); // OK but return IMessage types
它似乎工作,但它返回我 IMessage 类型。如何同时投射到 ICommandMessage?
在 Typescript 中使用 any 类型会非常有用。 ICommandMessage<any>
我找到了another subject related to this problem,但这对我没有帮助。
有什么想法吗?
【问题讨论】:
-
创建一个非泛型版本的
IEventMessage和ICommandMessage来继承泛型版本怎么样? -
在某些时候,这就是我所做的。但是在更高的级别(库),我需要处理不同类型的消息,而不管它们的通用类型。唯一重要的是它们的“主要”类型(事件、命令……)
-
查询的结果应该是什么?如果您将问题转换为
List<T>,则不能说List<> anyList = yourQuery.ToList()。您需要泛型类型参数。List<string>与List<int>不同。您的ICommandMessage<T>也是如此。 -
虽然您可以过滤这些泛型类型,但结果只能转换为
object。如果您需要访问 非泛型部分,则必须创建一个额外的非泛型接口并对其进行过滤。如果这不是有意或不可能的,那么您必须编写一些反射代码或使用dynamic(对于整个类型,而不仅仅是泛型参数)。 -
您正在处理一个不太适合您需求的类结构。显然,您需要一种逻辑方式来访问所有
CommandMessage对象(不管任何泛型参数),但您的代码一开始就不包含这种类型。这只是意味着您需要重新评估您的设计,以便它可以包含这样的类型。这种类型的外观很大程度上取决于您打算用它做什么。那么,在你获取了CommandMessage对象之后,你想用它们做什么呢?有什么涉及他们的通用属性吗?还是其他不依赖它的东西?