2

我有一个 Skype Bot 服务,它具有用于缩短给定 url 的定义接口。

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

该接口由两个服务实现,一个使用 Google Url Shorting API,另一个使用 TinyUrl API。

我的机器人在启动时加载了多个模块,每个模块在 SKype 客户端上注册监听事件。因此,当我在 Skype 中发送消息时:

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

然后我注册的模块已经监听了一个消息事件并分析了我的消息以检查它是否验证了它们在那里要做的事情,它们执行并返回一个小 url 的消息。

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 Modules 将两个 url 提供程序绑定到同一个父抽象模块,并根据其名称将不同的 IUrlShortenerProvider 注入该实例。除此之外,这是正确的方法吗?

public class TinyUrlProvider : IUrlShortenerProvider
public class GoogleUrlProvider : IUrlShortenerProvider

这样两个实现都被实例化了,如果一个实现匹配一个触发词,例如我UrlShortnerskypenetModule可以定义的“google”或“tinyurl”,那么适当的实例会处理请求吗?

到目前为止NinjectModul,我的 eUrlShortenerModule看起来像这样,但这是完全错误的,但希望能理解我想要完成的事情

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" 并将其声明为父对象,然后有两个具有相同父抽象对象的对象。我相信这就是我所追求的,但我从未在设置容器和依赖注入方面走得这么远。

4

1 回答 1

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", "");
于 2013-05-11T03:42:18.443 回答