使用SelfHosting时,我可以在app.config中自动托管所有服务吗?

Tra*_*vis 7 c# wcf self-hosting wcf-hosting

我正在编写一个需要托管多个WCF服务的应用程序.WCF的优势之一是能够通过在app.config文件中指定设置来配置服务而无需重新编译.

在自托管时,似乎没有一种开箱即用的方式来自动托管app.config文件中的服务.我发现这个问题提到了一个可能的解决方案,即在运行时动态枚举app.config中列出的服务,并为每个服务创建一个ServiceHost.

但是,我的服务,合同和托管应用程序都在不同的程序集中.这导致Type.GetType(string name)无法找到我的服务类型(返回null),因为它是在不同的程序集中定义的.

如何可靠地托管app.config文件中列出的所有服务(即,new ServiceHost(typeof(MyService))在我的自托管应用程序中没有硬编码?

注意:我的app.config是使用Visual Studio 2010中的"WCF配置编辑器"生成的.

另请注意:我的主要目标是由app.config文件驱动,因此只有一个配置点.我不想在一个单独的位置配置它.

编辑:我能够读取app.config文件(请参阅此处),但需要能够解析不同程序集中的类型.

编辑:下面的答案之一促使我尝试在app.config中指定AssemblyQualifiedName而不仅仅是基本类型名称.这能够解决Type.GetType()问题,但无论我如何获得类型,ServiceHost.Open()现在都失败了InvalidOperationException:

// Fails
string typeName = typeof(MyService).AssemblyQualifiedName;
Type myType = Type.GetType(typeName);
ServiceHost host = new ServiceHost(myType);
host.Open(); // throws InvalidOperationException

// Also fails
Type myType2 = typeof(MyService);
ServiceHost host2 = new ServiceHost(myType2);
host2.Open(); // throws InvalidOperationException
Run Code Online (Sandbox Code Playgroud)

例外细节:

Service 'SO.Example.MyService' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.

我想在内部解析app.config文件时,WCF会尝试匹配服务名称的文字字符串.

编辑/回答:我最终做的基本上是下面的答案.而不是使用Type.GetType()我知道我的所有服务都在同一个程序集中,所以我切换到:

// Get a reference to the assembly which contain all of the service implementations.
Assembly implementationAssembly = Assembly.GetAssembly(typeof(MyService));
...
// When loading the type for the service, load it from the implementing assembly.
Type implementation = implementationAssembly.GetType(serviceElement.Name);
Run Code Online (Sandbox Code Playgroud)

小智 5

    // get the <system.serviceModel> / <services> config section
    ServicesSection services = ConfigurationManager.GetSection("system.serviceModel/services") as ServicesSection;

    // get all classs
    var allTypes = AppDomain.CurrentDomain.GetAssemblies().ToList().SelectMany(s => s.GetTypes()).Where(t => t.IsClass == true);

    // enumerate over each <service> node
    foreach (ServiceElement service in services.Services)
    {
        Type serviceType = allTypes.SingleOrDefault(t => t.FullName == service.Name);
        if (serviceType == null)
        {
            continue;
        }

        ServiceHost serviceHost = new ServiceHost(serviceType);
        serviceHost.Open();
    }
Run Code Online (Sandbox Code Playgroud)

根据其他答案,我将代码扩展到以下内容,它在app.config中搜索所有程序集中的服务


Six*_*aez 1

您在问题链接中正确确定了问题的答案,@marc_s 答案也给出了正确的方法。您遇到的实际问题是,您需要动态获取只能通过配置文件引用的程序集的 Type 实例,因此它可能不会加载到当前的 AppDomain 中。

请参阅此博客文章,了解在代码中动态引用程序集的方法。尽管这篇文章专门针对 ASP.NET 应用程序,但一般方法应该适用于自托管场景。其想法是将 Type.GetType(string) 调用替换为私有方法调用,该方法动态加载请求的程序集(如果需要)并返回 Type 对象。您发送此方法的参数仍然是 element.Name,您需要确定哪个是要加载的正确程序集。一个简单的基于约定的程序集命名方案应该可行。例如,如果服务类型是:

MyNamespace.MyService.MyServiceImpl

然后假设程序集是:

我的命名空间.MyService