2013-04-27 73 views
2

我有一個Skype Bot服務,它具有用於縮短給定url的已定義接口。如何使用Ninject上下文綁定綁定多個實現

namespace Skypnet.Modules.UrlShortener 
{ 
    public interface IUrlShortenerProvider 
    { 
     string ApiKey { get; set; } 
     string Shorten(string url); 
    } 
} 

該接口由兩個服務實現,一個使用Google Url縮短API,另一個使用TinyUrl API。

我的機器人在啓動時會加載多個模塊,每個模塊都會在SKype客戶端上註冊監聽事件。所以,當我的Skype發送消息:

Patrick Magee>!tiny http://example.com/a-really-long-url-that-i-want-to-shorten 

然後,我已經聽了消息事件,並分析了我的信息註冊模塊檢查它是否驗證對他們是什麼那裏做,他們執行與返回一個小網址的消息。

Patrick Magee> Bot> http://tinyurl.com/2tx 

以略高的水平,我有一個定義的抽象Skypenet模塊,所有模塊Skypenet必須實現。

public class UrlShortenerSkypnetModule : AbstractSkypenetModule 

這個抽象模塊的唯一重要的事情是,它可以讓我UrlShortner註冊其爲Skype事件,像這樣:

public class UrlShortenerSkypnetModule : AbstractSkypenetModule 
{ 
    private readonly IUrlShortenerProvider urlShortenerProvider; 
    private const string RegexPatternV2 = @"^!(?<command>tiny)\s+(?<service>\S+?)\s+(?<url>(?<protocol>(ht|f)tp(s?))\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*))"; 
    //private const string RegexPattern = @"^!(?<command>tiny)\s+(?<url>(?<protocol>(ht|f)tp(s?))\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*))"; 
    private static readonly Regex UrlRegex = new Regex(RegexPatternV2, RegexOptions.Compiled); 

    /// <summary> 
    /// The Trigger used for this url shortener provider 
    /// </summary> 
    [Inject] 
    public string Trigger { get; set; } 

    [Inject] 
    public UrlShortenerSkypnetModule(IUrlShortenerProvider urlShortenerProvider) 
    { 
     if (urlShortenerProvider == null) 
      throw new ArgumentNullException("urlShortenerProvider"); 

     this.urlShortenerProvider = urlShortenerProvider; 
    } 

    public override void RegisterEventHandlers() 
    { 
     SkypeContainer.Skype.MessageStatus += SkypeOnMessageStatus; 
    } 

    private void SkypeOnMessageStatus(ChatMessage pMessage, TChatMessageStatus status) 
    { 
     if (status == TChatMessageStatus.cmsSent || status == TChatMessageStatus.cmsReceived) 
     { 
      Match match = UrlRegex.Match(pMessage.Body); 

      if (match.Success) 
      { 
       var url = match.Groups["url"].Value; 
       var trigger = match.Groups["service"].Value; 

       // If the service matches 
       if (trigger.ToLower().Equals(Trigger.ToLower())) 
       { 
        string shorten = urlShortenerProvider.Shorten(url); 
        pMessage.Chat.SendMessage(shorten); 
       } 
      } 
     } 
    } 
} 

如何使用Ninject模塊綁定兩個URL提供給相同的父級抽象模塊並基於其名稱將不同的IUrlShortenerProvider注入該實例。除此之外,這是否是正確的方式呢?

public class TinyUrlProvider : IUrlShortenerProvider 
public class GoogleUrlProvider : IUrlShortenerProvider 

這樣既實現是實例化,如果實現匹配 一個觸發字,如「谷歌」或我UrlShortnerskypenetModule可以定義「TinyURL的」,相應的實例處理請求?

到目前爲止,我有一個NinjectModul E對於我UrlShortenerModule它看起來像這樣,但它是完全錯誤的,但希望給出了什麼,我想acomplish

public class UrlShortenerModules : NinjectModule 
{ 
    public override void Load() 
    { 
     // The Abstract Module which all Modules must implement 
     Bind<ISkypnetModule>() 
      .To<AbstractSkypenetModule>() 
      .Named("UrlShortener") 
      .WithPropertyValue("Name", "Minify") 
      .WithPropertyValue("Description", "Produces a minified url of a given url.") 
      .WithPropertyValue("Instructions", "!tiny [service] [url] i.e '!tiny google http://example.com/a-really-long-url-you-want-to-minify'"); 

     // Well we have a Google url service 
     // but i want this service to have the same abstract parent 
     // as the tinyurl service - since both are part of the minify module 
     Bind<ISkypnetModule>() 
      .To<UrlShortenerSkypnetModule>() 
      .WhenParentNamed("UrlShortener") 
      .Named("Google") 
      .WithPropertyValue("Trigger", "google"); 

     // We also have a tiny url service 
     // but i want this service to have the same abstract parent 
     // as the google service - since both are part of the minify module 
     Bind<ISkypnetModule>() 
      .To<UrlShortenerSkypnetModule>() 
      .WhenParentNamed("UrlShortener") 
      .Named("Tinyurl") 
      .WithPropertyValue("Trigger", "tinyurl"); 

     // Well the tiny url provider should be injected 
     // into urlshortener named tinyurl 
     Bind<IUrlShortenerProvider>() 
      .To<TinyUrlProvider>() 
      .WhenParentNamed("Tinyurl") 
      .WithPropertyValue("ApiKey", ""); 

     // Well the google url service should be injected 
     // into urlshortener named google 
     Bind<IUrlShortenerProvider>() 
      .To<GoogleUrlProvider>() 
      .WhenParentNamed("Google") 
      .WithPropertyValue("ApiKey", ""); 
    } 
} 

瞭解我見過的某種與Spring.NET配置類似的行爲,您可以在Spring.config中定義對象並將abstract =「true」並將其聲明爲父對象,然後讓兩個對象具有相同的父抽象對象。我相信這就是我所追求的,但我從來沒有這麼做過設置容器和依賴注入。

回答

1

似乎我在我的回答中聲明的方式是正確的解決方法。所以答案是聲明多個綁定,這應該創建新的實例在同一個SkypenetModule中工作。由於兩者都基於該.Named UrlShortenerSkypenetModule實例化

Bind<ISkypnetModule>() 
     .To<UrlShortenerSkypnetModule>() 
     .WhenParentNamed("UrlShortener") 
     .Named("Google") 
     .WithPropertyValue("Trigger", "google"); 


    Bind<ISkypnetModule>() 
     .To<UrlShortenerSkypnetModule>() 
     .WhenParentNamed("UrlShortener") 
     .Named("Tinyurl") 
     .WithPropertyValue("Trigger", "tinyurl"); 


    Bind<IUrlShortenerProvider>() 
     .To<TinyUrlProvider>() 
     .WhenParentNamed("Tinyurl") 
     .WithPropertyValue("ApiKey", ""); 


    Bind<IUrlShortenerProvider>() 
     .To<GoogleUrlProvider>() 
     .WhenParentNamed("Google") 
     .WithPropertyValue("ApiKey", ""); 
+1

好走帕特里克,起初我還以爲您的解決方案過於複雜,你可以使用一個簡單的查找字典, 但使用Ninject會自己做幫助您更輕鬆地測試解決方案並更好地管理依賴關係。 – 2013-05-11 14:18:13

+0

感謝您的關注! – 2013-05-11 14:22:43