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

时间:2014-03-18 16:15:58

标签: c# asp.net-mvc ninject constructor-injection

我有一个服务类,它也在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>

1 个答案:

答案 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;
    }
}