是否可以使用Ninject在注入的类构造函数中解析URL ?

本文关键字:构造函数 URL 可以使 Ninject 注入 是否 | 更新日期: 2023-09-27 17:50:52

我有一个在ASP中使用的服务类。Net MVC 5 web应用程序和控制台应用程序。我们叫它MyService。当MyService对象被Ninject实例化并传递给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构造函数必须知道它被注入的控制器类,并且能够从该控制器调用方法。如果没有已知的控制器类,那么它将使用应用程序的设置。

当然,我也可以在传入MyService对象的每个控制器构造函数中设置url参数,也可以在控制台应用程序的其他地方设置url参数,但我不希望每次实例化MyService对象时都要设置这个属性。

是否可以使用Ninject在注入的类构造函数中解析URL ?

我们从:

开始
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;
    }
}