代码之家  ›  专栏  ›  技术社区  ›  Oliver

在托管在ASP.NET应用程序中的WCF服务中使用Autofac for DI

  •  14
  • Oliver  · 技术社区  · 16 年前

    我在使用Autofac 1.4.5将服务依赖项注入WCF服务时遇到问题。我读过并跟踪了 Autofac wiki page on WcfIntegration 但我的调试表明,我的WCF服务是由 System.ServiceModel.Dispatcher.InstanceBehavior.GetInstance() 方法而不是 AutofacWebServiceHostFactory . 我做错什么了?

    我已经设置了 ajax.svc 与示例中类似的文件,用于 WebHttpBinding :

    <%@ ServiceHost Language="C#" Debug="true"
        Service="Generic.Frontend.Web.Ajax, Generic.Frontend.Web"
        Factory="Autofac.Integration.Wcf.AutofacWebServiceHostFactory,
                 Autofac.Integration.Wcf" %>
    

    我的WCF服务类 Ajax 定义如下:

    namespace Generic.Frontend.Web
    {
        [ServiceContract]
        [AspNetCompatibilityRequirements(
            RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class Ajax
        {
            public MapWebService MapWebService { get; set;}
    
            public Ajax() {
                // this constructor is being called
            }
    
            public Ajax(MapWebService mapWebService)
            {
                // this constructor should be called
                MapWebService = mapWebService;
            }
    
            [WebGet(ResponseFormat = WebMessageFormat.Json)]
            [OperationContract(Name = "mapchange")]
            public MapChangeResult ProcessMapChange(string args)
            {
                // use the injected service here
                var result = MapWebService.ProcessMapChange(args);
                return result;
            }
        }
    }
    

    现在我用了 Global.asax.cs 如上面提到的wiki所示:

    var builder = new ContainerBuilder();
    builder.RegisterModule(new AutofacModuleWebservice());
    var container = builder.Build();
    AutofacServiceHostFactory.Container = container;
    

    具有

    class AutofacModuleWebservice : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.Register<Ajax>();
            builder.Register<MapWebService>().ContainerScoped();
        }
    }
    

    在我的web.config中

    <services>
        <service name="Generic.Frontend.Web.Ajax">
            <endpoint address="http://mysite.com/ajax.svc/" binding="webHttpBinding"
                      contract="Generic.Frontend.Web.Ajax" />
        </service>
    </services>
    

    .

    该服务已经运行良好,但我无法让Autofac位(读取:创建/注入)工作。有什么想法吗?

    编辑: 很遗憾,删除默认构造函数会导致以下异常:

    System.InvalidOperationException:
    The service type provided could not be loaded as a service because it does not
    have a default (parameter-less) constructor. To fix the problem, add a default
    constructor to the type, or pass an instance of the type to the host.
    

    干杯,奥利弗

    5 回复  |  直到 16 年前
        1
  •  1
  •   Jon    16 年前

    您的服务是否设置为InstanceContextMode.Single?如果是,则wcf将使用默认构造函数创建服务。若要解决此问题,请更改实例上下文模式并让autofac管理服务的生存期。

        2
  •  0
  •   Igor Zevaka    16 年前

    尝试删除默认值 Ajax 构造函数并将构造函数修改为此。如果它和 mapWebService == null 这将意味着解决问题。

        public Ajax(MapWebService mapWebService = null)
        {
            // this constructor should be called
            MapWebService = mapWebService;
        }
    
        3
  •  0
  •   Damien McGivern    15 年前

    我刚得到相同的System.InvalidOperationException,并通过将实现的ServiceBehavior InstanceContextMode从InstanceContextMode.PerCall更改为InstanceContextMode.PerSession解决了它,也许您的AutoFac生存期范围与您的web服务实现不同步?

    对于测试AutoFac服务创建,我建议创建一个单元测试并直接解决它们,因为这将突出显示任何问题并给出更有意义的异常消息。对于具有请求生存期作用域的服务,创建一个测试aspx页,然后再次直接解析它们。

        4
  •  0
  •   Jeff Ogata    15 年前

    我也有同样的问题,在寻找答案时遇到了这个问题。

    在我的例子中,使用属性注入是可行的,并且问题中的代码已经有一个可以使用的属性:

    namespace Generic.Frontend.Web
    {
        [ServiceContract]
        [AspNetCompatibilityRequirements(
            RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class Ajax
        {
            // inject the dependency here
            public MapWebService MapWebService { get; set;}
    
            [WebGet(ResponseFormat = WebMessageFormat.Json)]
            [OperationContract(Name = "mapchange")]
            public MapChangeResult ProcessMapChange(string args)
            {
                // use the injected service here
                var result = MapWebService.ProcessMapChange(args);
                return result;
            }
        }
    }
    

    并注册以使用属性注入(来自wiki的示例代码和语法已更改,因为现在使用的是版本2.5.2.830):

    builder.RegisterType<Ajax>().PropertiesAutowired();
    
        5
  •  0
  •   Johan    13 年前

    按照指示为我解决了这个问题:

    code.google.com/p/autofac/wiki/I简单地做:builder.RegisterType();

    我已经按照他们的指示修改了.svc文件。

    当你查看你的.svc文件时,你没有得到任何关于出错的提示?

    如果您通过iis托管它,而不使用WAS,我看不到您重写global.asax.cs的代码

    将全局文件添加到解决方案中,然后在其中实现:

      protected void Application_Start(object sender, EventArgs e)
            {
                // build and set container in application start
                IContainer container = AutofacContainerBuilder.BuildContainer();
                AutofacHostFactory.Container = container;
    
    
            }
    

    AutofacContainerBuilder是我的容器生成器。

    推荐文章