我有一个服务类,它也在ASP.Net MVC 5 Web应用程序和控制台应用程序中使用。我们称之为MyService。当Ninject将MyService对象实例化为传递给Web上下文中的控制器时,我希望使用类似的东西来解析URL
url = Request.Url.GetLeftPart(UriPartial.Authority) + Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Emailer" });
当MyService由我的控制台应用程序实例化时(也使用Ninject,但在非Web上下文中),我希望它从AppSettings中获取这样的URL:
url = ConfigurationManager.AppSettings["EmailerUrl"];
这可行吗?我认为在创建绑定时可能正在使用WithConstructorArgument()和NinjectWebCommon.RegisterServices(IKernel内核)中的正确参数,但我不知道具体如何。
我的猜测是MyService构造函数必须知道注入它的控制器类,并能够从该控制器调用方法。如果没有已知的控制器类,那么它将使用应用程序设置。
当然,我也可以在每个控制器构造函数中设置url参数传递MyService对象,以及控制台应用程序中的其他位置,但我不想担心每次实例化MyService对象时都要设置此属性。 / p>
答案 0 :(得分:1)
所以让我们从:
开始public interface IUrl
{
Url Url { get; }
}
internal class ControllerBasedUrl : IUrl
{
public ControllerBasedUrl(string controllerName)
{
this.Url = null; // implement
}
public Url Url { get; private set; }
}
internal class AppConfigBasedUrl : IUrl
{
public AppConfigBasedUrl()
{
this.Url = null; // implement
}
public Url Url { get; private set; }
}
您可以使用多种方法:
a)让应用程序知道您是在web应用程序或控制台应用程序中运行,然后使用条件绑定:
var kernel = new StandardKernel();
if (runningInConsoleApplication)
{
kernel.Bind<IUrl>().To<AppConfigBasedUrl>();
}
else
{
kernel.Bind<IUrl>().ToMethod(ctx =>
{
IRequest controllerRequest = ctx.Request.TraverseRequestChainAndFindMatch(x => x.Target.Name.EndsWith("Controller"));
return new ControllerBasedUrl(controllerRequest.Target.Type.Name);
});
}
b)使url的绑定取决于它是否被注入控制器:
var kernel = new StandardKernel();
kernel.Bind<IUrl>().ToMethod(ctx =>
{
IRequest controllerRequest = ctx.Request.TraverseRequestChainAndFindMatch(x => x.Target.Name.EndsWith("Controller"));
if (controllerRequest != null)
{
return new ControllerBasedUrl(controllerRequest.Target.Type.Name);
}
return new AppConfigBasedUrl();
});
都使用此扩展程序:
public static class RequestExtensions
{
public static IRequest TraverseRequestChainAndFindMatch(this IRequest request, Func<IRequest, bool> matcher)
{
if (matcher(request))
{
return request;
}
if (request.ParentRequest != null)
{
return request.ParentRequest.TraverseRequestChainAndFindMatch(matcher);
}
return null;
}
}