我有一个WCF服务库,其中包含从DefaultServiceHostFactory派生的自定义ServiceHostFactory。我无法让测试客户端使用此工厂。我只是得到了“找不到无参数构造器”的错误。
这是我的托管环境配置:
<serviceHostingEnvironment>
  <serviceActivations>
    <add service="TestService.WcfLibrary.TestService"
         relativeAddress="/TestService.svc"
         factory="TestService.WcfLibrary.TestServiceHostFactory, TestService.WcfLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </serviceActivations>
</serviceHostingEnvironment>请注意,我实际上没有.svc文件。我正在尝试使用无文件激活。
下面是我的自定义ServiceHostFactory:
public class TestServiceHostFactory : DefaultServiceHostFactory
{
    public TestServiceHostFactory() : base(CreateKernel()) { }
    private static IKernel CreateKernel()
    {
        WindsorContainer container = new WindsorContainer();
        container.AddFacility<WcfFacility>();
        container.Register(Component.For<TestService>());
        container.Register(Component.For<IServiceManager>().ImplementedBy<ServiceManager>());
        return container.Kernel;
    }
}看起来这条路径从来没有执行过。如何让WCF测试客户端使用我的自定义实现?
发布于 2012-04-13 15:02:35
好吧,这是可能的,但它不是很好……
首先,我们需要一种在加载程序集时挂钩的方法,因为在这种情况下,它们不是“主”或“应用程序启动”或任何东西。在AppDomain上有一个名为AssemblyLoaded的有趣事件,看起来它可能会做到这一点,嗯,但是如何挂钩它,我认为实现这一点的一种方法是定义一个自定义的应用程序域管理器,所以……
创建一个全新的程序集,并在其中定义一个接口,该接口可以由一些客户端和AppDomainManager实现,如下所示:
public interface IAssemblyLoaded
{
    void AssemblyLoaded();
}
public class CustomManager : AppDomainManager
{
    public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
    {
        base.InitializeNewDomain(appDomainInfo);
        // Look for any classes that implement IAssemblyLoaded,
        // constuct them (will only work if they have a default constructor)
        // and call the AssemblyLoaded method
        var loaded = typeof (IAssemblyLoaded);
        AppDomain
            .CurrentDomain
            .AssemblyLoad += (s, a) =>
                                 {
                                     var handlers = a
                                         .LoadedAssembly
                                         .GetTypes()
                                         .Where(loaded.IsAssignableFrom);
                                     foreach (var h in handlers)
                                     {
                                         ((IAssemblyLoaded)
                                          Activator.CreateInstance(h))
                                             .AssemblyLoaded();
                                     }
                                 };
    }
}确保程序集已签名,然后将其添加到GAC。假设我调用了程序集AssemblyInitCustomDomainManager,我可以像这样添加它(并且我立即获得了关于它的详细信息,因为我将需要它们):
gacutil /i AssemblyInitCustomDomainManager.dll
gacutil /l AssemblyInitCustomDomainManager现在编辑WcfServiceHost.exe.config (通常位于: C:\Program Files\Microsoft Visual Studio10.0\Common7\IDE或64位系统上的x86版本),并在运行时元素中添加以下内容(有关此设置的信息,请参阅here ):
<appDomainManagerType value="AssemblyInitCustomDomainManager.CustomManager" />
<appDomainManagerAssembly value="AssemblyInitCustomDomainManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c841b3549556e52a, processorArchitecture=MSIL" />注意:您将需要至少更改其中之一(也可能全部更改,这取决于您在上面调用的内容):类型名称、命名空间、程序集名称、公钥、版本号。我想你应该能弄清楚它们在你的箱子里需要什么。
好了,这很简单,现在我们将在visual studio中创建一个新的"WCF Service Library“项目,它将为我们创建一个app.config和一个服务(这是您想要测试的项目类型,哦,我希望如此!)。
首先,从app.config中删除system.servicemodel部件,因为我们不希望服务主机应用程序读入此部件,然后删除Service1.cs和IService1.cs (稍后我将创建自己的部件)。确保引用之前创建的应用程序域管理器程序集,因为您需要实现该接口。
现在,创建一个新文件并插入以下代码(我们只有一个简单的服务,该服务具有Castle WCF Facility托管的依赖项):
using System;
using System.ServiceModel;
using AssemblyInitCustomDomainManager;
using Castle.Facilities.WcfIntegration;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using Castle.Windsor.Installer;
namespace TestWcfServiceLibrary
{
    public class AssemblyInitializedHandler : IAssemblyLoaded
    {
        // This method is called when the assembly loads so we will create the
        // windsor container and run all the installers we find
        public void AssemblyLoaded()
        {            
            new WindsorContainer().Install(FromAssembly.This());            
        }        
    }
    // This installer will set up the services
    public class ServicesInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, 
                            IConfigurationStore store)
        {
            container
                .AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero)
                .Register(Component
                              .For<ITestDependency>()
                              .ImplementedBy<TestDependency>(),
                          Component
                              .For<IService1>()
                              .ImplementedBy<Service1>()
                              .AsWcfService(new DefaultServiceModel(WcfEndpoint
                                                                        .BoundTo(new WSHttpBinding()))
                                                .AddBaseAddresses("http://localhost:9777/TestWcfServiceLibrary/Service1")
                                                .PublishMetadata(m => m.EnableHttpGet())));
        }
    }
    // This is the contract of something we want to make sure is loaded
    // by Windsor
    public interface ITestDependency
    {
        int DoSomething(int value);
    }
    public class TestDependency : ITestDependency
    {
        public int DoSomething(int value)
        {
            return value;
        }
    }
    // Regular WCF service contract
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);
    }
    // Service implementation - notice it does not have a default 
    // constructor
    public class Service1 : IService1
    {
        private readonly ITestDependency _td;
        public Service1(ITestDependency td)
        {
            _td = td;
        }
        public string GetData(int value)
        {
            int v = _td.DoSomething(value);
            return string.Format(
                "According to our dependency you entered: {0}", v);
        }
    }
}单击run,您将看到一条错误消息,内容为:
WCF服务主机找不到任何服务元数据。这可能会导致客户端应用程序运行不正常。请检查元数据是否启用。是否要退出?
不用担心,只需单击no即可。
测试客户端启动,但遗憾的是它没有您的服务。不用担心,只需右键单击添加服务...并放入服务的URL (它在安装程序中的代码-http://localhost:9777/TestWcfServiceLibrary/Service1中)。
这就是WCF Test Client内部托管的WCF服务。不要相信我-测试它,调用GetData操作,您应该会看到结果。
这就对了。现在,如果你问这是不是一个好主意…我不知道,但它是有效的,我认为这是你所要求的…
https://stackoverflow.com/questions/10058761
复制相似问题