我有一个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\-\.\?\,\'\/\\\+&%\$#_]*))";
//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\-\.\?\,\'\/\\\+&%\$#_]*))";
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”并将其声明为父对象,然后让两个对象具有相同的父对象抽象的对象。我相信这就是我所追求的,但我从来没有在设置容器和依赖注入方面走得太远。
答案 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", "");