首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DryIoc.WebApi设置

DryIoc.WebApi设置
EN

Stack Overflow用户
提问于 2016-04-27 20:02:33
回答 2查看 3.1K关注 0票数 3

我正在探索DryIoc在.NET WebAPI应用程序中的使用,并注意到初始化步骤中有一种奇怪的行为。在一个简单的测试webapi应用程序中,我有下面的DryIoc注册类,它在WebApi配置注册之后立即调用。

代码语言:javascript
复制
public class DryIocConfig
{
    public static void Register(HttpConfiguration config)
    {
        var c = new Container().WithWebApi(config);

        c.Register<IWidgetService, WidgetService>(Reuse.Singleton);
        c.Register<IWidgetRepository, WidgetRepository>(Reuse.Singleton);
    }
}

以及以下WebApi控制器:

代码语言:javascript
复制
public class ValuesController : ApiController
{
    private readonly IWidgetService _widgetService;

    public ValuesController(IWidgetService widgetService)
    {
        _widgetService = widgetService;
    }

    // GET api/values
    public IEnumerable<Widget> Get()
    {
        return _widgetService.GetWidgets();
    }
}

这似乎很好,但在我看来,在尝试是相同的,但写得更详细,代码我得到了一个错误。

代码语言:javascript
复制
public class DryIocConfig
{
    public static void Register(HttpConfiguration config)
    {
        var c = new Container();
        c.WithWebApi(config);  // Now separate statement rather than chained. 

        c.Register<IWidgetService, WidgetService>(Reuse.Singleton);
        c.Register<IWidgetRepository, WidgetRepository>(Reuse.Singleton);
    }
}

我得到的例外是以下(作为JSON):

代码语言:javascript
复制
    {
        "Message" : "An error has occurred.",
        "ExceptionMessage" : "An error occurred when trying to create a controller of type 'ValuesController'. Make sure that the controller has a parameterless public constructor.",
        "ExceptionType" : "System.InvalidOperationException",
        "StackTrace" : "   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n   at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()",
        "InnerException" : {
            "Message" : "An error has occurred.",
            "ExceptionMessage" : "Type 'IOCContainerTest.DryLoc.Controllers.ValuesController' does not have a default constructor",
            "ExceptionType" : "System.ArgumentException",
            "StackTrace" : "   at System.Linq.Expressions.Expression.New(Type type)\r\n   at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"
        }
    }

这是DryIoc的奇怪之处,还是我从未遇到过的C#细微差别?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-27 20:48:13

这是因为.WithWebApi()是每个来源的扩展方法。

代码语言:javascript
复制
 public static IContainer WithWebApi(this IContainer container, HttpConfiguration config,
        IEnumerable<Assembly> controllerAssemblies = null, IScopeContext scopeContext = null,
        Func<Type, bool> throwIfUnresolved = null)
    {
        container.ThrowIfNull();

        if (container.ScopeContext == null)
            container = container.With(scopeContext: scopeContext ?? new AsyncExecutionFlowScopeContext());

        container.RegisterWebApiControllers(config, controllerAssemblies);

        container.SetFilterProvider(config.Services);

        InsertRegisterRequestMessageHandler(config);

        config.DependencyResolver = new DryIocDependencyResolver(container, throwIfUnresolved);

        return container;
    }

在第一个语法示例中,您创建了一个新的Container实例,并将新创建的实例传递给.WithWebApi()。这反过来更新容器实例,并最终将其返回给变量c

在第二个语法示例中,您永远不会将扩展方法的值返回到原始变量,并对其进行更新。您正在调用它,就好像它是一个void方法一样,在本例中它什么也不做,因此出现了异常。

如果你写的是:

代码语言:javascript
复制
var c = new Container();
c = c.WithWebApi(config);

它本质上是第一种语法的一个更详细的示例,并使用新的功能正确地更新了c

票数 3
EN

Stack Overflow用户

发布于 2016-04-27 20:54:48

这似乎很好,而且应该有效。显然,从ccontainer.WithWebApi(config);返回的容器不是原始容器,这在这一点上是出乎意料的,因此至少有一种代码气味,因为它会产生可能的bug。最好编写几个单元测试,并在DryIoC Bitbucket站点上打开一个问题。

为了帮助您,这里有一个如何编写此类测试的模板。创建一个新的测试项目并执行以下操作:

安装NuGet软件包

代码语言:javascript
复制
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
Install-Package DryIoc.WebApi.Owin.dll
Install-Package Xunit 

控制器

代码语言:javascript
复制
public sealed class ValuesController : ApiController
{
    private IWidgetService WidgetService { get; }

    public ValuesController(IWidgetService widgetService)
    {
        if(widgetService == null) 
            throw new ArgumentNullException(nameof(widgetService));
        WidgetService = widgetService;
    }

    [HttpGet]
    public IEnumerable<Widget> Get()
    {
        return WidgetService.GetWidgets().ToArray();
    }
}

OWIN启动

代码语言:javascript
复制
public sealed class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration()
            .ConfigureRouting()
            .ConfigureDependencyInjection();

        app.UseWebApi(config);

        // protip: use OWIN error page instead of ASP.NET yellow pages for better diagnostics 
        // Install-Package Microsoft.Owin.Diagnostics
        // app.UseErrorPage(ErrorPageOptions.ShowAll); 
    }

    private static HttpConfiguration ConfigureRouting(this HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "default", 
            routeTemplate: "/", 
            defaults: new { controller = "values" });
        return config;
    }

    private static HttpConfiguration ConfigureDependencyInjection(this HttpConfiguration config)
    {
        new Container()
            .Register<IWidgetService, WidgetService>(Reuse.Singleton)
            .Register<IWidgetRepository, WidgetRepository>(Reuse.Singleton)
            .WithWebApi(config);
        return config;
    }
}

单元测试

代码语言:javascript
复制
[Fact]
public async Task ShouldFoo()
{
    const string baseAddress = "http://localhost:8000";
    using (WebApp.Start<Startup>(baseAddress))
    {
        var httpclient = new HttpClient
        { 
            BaseAddress = new Uri(baseAddress)
        };
        var response = await httpclient.GetAsync("/");
        Assert.That(...);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36899798

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档