私はここで説明されているアプローチをうまく使用しました:
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ベースのエンドポイントで機能するアプローチについて説明しています。