Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
145 views
in Technique[技术] by (71.8m points)

c# - Can I automatically host all services in app.config when using SelfHosting?

I'm writing an application which needs to host several WCF services. One of the strengths of WCF is the ability to configure services without having to recompile, by specifying settings in the app.config file.

When self-hosting, there does not appear to be an out-of-the-box way to automatically host services which are in the app.config file. I found this question which mentions a possible solution of dynamically enumerating services listed in app.config at runtime, and creating a ServiceHost for each.

However, my services, contracts, and the hosting application are all in different assemblies. This causes Type.GetType(string name) to fails to locate my service type (returns null) because it is defined in a different assembly.

How can I reliably host all services listed in the app.config file dynamically (i.e., without hard-coding new ServiceHost(typeof(MyService)) in my self-hosting application?

Note: My app.config was generated using the "WCF Configuration Editor" in Visual Studio 2010.

Note also: My primary goal is to have this driven by the app.config file so there is a single point of configuration. I don't want to have to configure this in a separate location.

EDIT: I am able to read the app.config file (see here), but need to be able to resolve types in different assemblies.

EDIT: One of the answers below prompted me to try specifying the AssemblyQualifiedName in app.config instead of just the basic type name. This was able to get around the Type.GetType() problem, however ServiceHost.Open() now fails with an InvalidOperationException regardless of how I attain the type:

// 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

Exception details:

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.

I guess WCF attempts to match the literal string for the service name when parsing the app.config file internally.

EDIT/ANSWER: What I ended up doing was basically what was in the answer below. Instead of using Type.GetType() I know that all of my services are in the same assembly, so I switched to:

// 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);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
    // 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();
    }

Based on the other answers, I extended the code to the following, which searches all assemblies for the services in the app.config


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...