基于类型
问题描述:
动态创建对象,我有以下代码:基于类型
public async Task DispatchAsync(NoticeChannelType type, string message)
{
switch (type)
{
case NoticeChannelType.Email:
{
var email = JsonConvert.DeserializeObject<NoticeEmail>(message);
await _channelResolver.ResolveAsync(email);
}
break;
case NoticeChannelType.Pushover:
{
var pushover = JsonConvert.DeserializeObject<NoticePushover>(message);
await _channelResolver.ResolveAsync(pushover);
}
break;
default:
break;
}
}
我想以某种方式删除此开关,创建并把对象的具体类型。
的channelResolver.ResolveAsync
后实现如下:
public async Task ResolveAsync<T>(T channel) where T : INoticeChannel
{
if (channel == null)
throw new ArgumentNullException(nameof(channel),
$"Channel: '{typeof(T).Name}' cannot be null.");
var handler = _context.Resolve<INoticeExecutor<T>>();
await handler.SendAsync(channel);
}
我试图将它重构到这样的事情:
public async Task DispatchAsync(NoticeChannelType type, string message)
{
var channel = _context.ResolveKeyed<INoticeChannel>(type);
Type myType = Type.GetType(channel.GetType().FullName);
await _channelResolver.ResolveAsync((INoticeChannel)JsonConvert.DeserializeObject(message, myType));
}
但之后在channelResolver.ResolveAsync
型T
是INoticeChannel
,而不是具体类型如此_context.Resolve<INoticeExecutor<T>>();
无法解决它。
这是可能删除此开关,并使此代码更优雅,更容易维护?
答
您可以使用反射或DLR Dynamic Dispatch调用ResolveAsync
泛型方法,但我不知道它会使代码更优雅(前者是丑陋的像任何反射代码),并更容易维护(与你失去这两种技术编译时的类型安全性)。
但在这里你去:
反思:
public async Task DispatchAsync(NoticeChannelType type, string message)
{
var channelType = _context.ResolveKeyed<INoticeChannel>(type).GetType();
var channel = JsonConvert.DeserializeObject(message, channelType);
var resolveMethod = _channelResolver.GetType().GetMethod("ResolveAsync")
.MakeGenericMethod(channelType);
await (Task)resolveMethod.Invoke(_channelResolver, new object[] { channel });
}
(如果ResolveAsync
是接口方法,用typeof(IChannelResolver)
取代_channelResolver.GetType()
其中IChannelResolver
是你的接口名称)
DLR动态调度:
public async Task DispatchAsync(NoticeChannelType type, string message)
{
var channelType = _context.ResolveKeyed<INoticeChannel>(type).GetType();
var channel = JsonConvert.DeserializeObject(message, channelType);
await (Task)_channelResolver.ResolveAsync((dynamic)channel);
}
非常感谢,我知道我们不能拥有所有东西(优雅,易于维护等),但我希望在这种情况下我能处理它。 –