基于类型

问题描述:

动态创建对象,我有以下代码:基于类型

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.ResolveAsyncTINoticeChannel,而不是具体类型如此_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); 
} 
+0

非常感谢,我知道我们不能拥有所有东西(优雅,易于维护等),但我希望在这种情况下我能处理它。 –