2017-05-30 109 views
1

動態創建對象,我有以下代碼:基於類型

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>>();無法解決它。

這是可能刪除此開關,並使此代碼更優雅,更容易維護?

回答

1

您可以使用反射或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

非常感謝,我知道我們不能擁有所有東西(優雅,易於維護等),但我希望在這種情況下我能處理它。 –