1

我有一个在 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 kernel) 中的正确参数,但我不知道具体如何。

我的猜测是 MyService 构造函数必须知道注入它的控制器类,并能够从该控制器调用方法。如果不知道控制器类,那么它将使用应用程序设置。

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

4

1 回答 1

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;
    }
}
于 2014-03-19T08:56:23.650 回答