如何使用Ninject上下文绑定绑定多个实现

时间:2013-04-27 05:13:05

标签: ninject spring.net

我有一个Skype Bot服务,它有一个用于缩短给定网址的已定义界面。

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

public class TinyUrlProvider : IUrlShortenerProvider
public class GoogleUrlProvider : IUrlShortenerProvider

这样两个实现都是实例化的,如果实现匹配的话 一个触发词,例如我的UrlShortnerskypenetModule可以定义的“google”或“tinyurl”,相应的实例会处理请求吗?

到目前为止,我的NinjectModul有一个UrlShortenerModule e,看起来像这样,但它完全错了,但希望能够理解我想要实现的目标

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 个答案:

答案 0 :(得分: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", "");