0

我试图寻找解决方案,但到目前为止我没有运气。

我有一系列类库,每个库(模块/插件)实现一个或多个 WCF 服务。现在我想要一个“托管”项目,我可以在其中根据可访问的插件添加所有这些服务。我知道我可以使用无文件激活,因此可以在所有配置时间内完成,但我更希望有一些代码来查看已安装的插件(我有代码),并添加暴露的服务运行时。整个事情应该使用 WAS 托管在 IIS 7(或更高版本)中,因为我需要 TCP 绑定以及 HTTP。

我发现似乎可以使用 ASP.NET RouteTable 类(在 Application_Start 中添加类型),但我的理解是这将限制我仅使用 HTTP 托管。

我想我想要的是一个用于 WAS 的 API,我可以连接并添加“端点/激活”,但到目前为止我还没有找到任何东西。相当于以下配置的东西:

<serviceActivations>
    <add relativeAddress="AwesomeService.svc" service="Classlibrary.WCF.AwesomeService"/>
</serviceActivations>

任何人都知道如何做到这一点?

4

1 回答 1

0

我已经成功地使用了这里描述的方法:

http://weblogs.asp.net/andresv/archive/2011/08/29/registering-a-wcf-service-dynamically.aspx

它使用一些反射黑客来访问 ServiceHostingEnvironment 类上的私有字段,以在运行时添加自定义的“基于配置的激活”条目。

我选择使用 HttpModule 来注册服务激活元素,如下所示:

    public class ServiceRegistrationModule : IHttpModule
    {
        public void Dispose()
        {
        }

        public void Init(HttpApplication context)
        {
            // Discover and register your services here
            RegisterService("~/Some/Path.svc", null, "The full service class name");
        }

        static object _syncRoot = new object();
        static Hashtable serviceActivations;

        private static void RegisterService(string addr, string factory, string service)
        {
            // This is the code that injects the service activation configuration.
            // In WCF 4 we have the "not very well known" CBA Services (Configuration Based Activation)
            // to allow us to define "file-less" WCF Services (like our Service2 here in this demo) where
            // we have a section in our web.config to register services without the need of having a physical .svc file.
            // The section in the web.config looks like this:
            //
            //      <serviceHostingEnvironment multipleSiteBindingsEnabled="true" >
            //          <serviceActivations>
            //              <add relativeAddress="Service2.svc" service="WcfService2.Service2" />
            //          </serviceActivations>
            //      </serviceHostingEnvironment>
            //
            // And is this configuration what we are going to inject at runtime to simulate having that 
            // information in our web.config, while we haven't.

            lock (_syncRoot)
            {
                if (serviceActivations == null)
                {
                    var ensureInitialized = typeof(ServiceHostingEnvironment).GetMethod("EnsureInitialized");
                    ensureInitialized.Invoke(null, new object[] { });
                    var hostingManagerField = typeof(ServiceHostingEnvironment).GetField("hostingManager", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField);
                    var hostingManager = hostingManagerField.GetValue(null);
                    var serviceActivationsField = hostingManager.GetType().GetField("serviceActivations", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
                    serviceActivations = (Hashtable)serviceActivationsField.GetValue(hostingManager);
                }

                if (!serviceActivations.ContainsKey(addr))
                {
                    string value = string.Format("{0}|{1}|{2}", addr, factory, service);
                    serviceActivations.Add(addr, value);
                }
            }
        }
    }

使用 HttpModule 的缺点是它不适用于基于 TCP 的端点。这对我来说不是一个问题。如果这对您来说是个问题,我上面引用的博客文章描述了一种适用于基于 TCP 的端点的方法。

于 2013-05-20T19:43:25.163 回答