HttpModuleにパラメータを渡す方法
HttpModule好きなんですが、JavaのServlet Filterのように設定でパラメータを渡せないのが残念なところです。そこで、Web.configにパラメータを設定をすればHttpModuleのプロパティに自動で設定される仕組みを考えてみました。
例えば、Web.configに以下の感じで記述して、MyModuleのTimeoutプロパティに10を設定したいのです。
<configSections>
<sectionGroup name="my.system.webServer">
<section name="modules" type="WebApplication.ModulesSection, WebApplication" />
</sectionGroup>
</configSections><system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="MyModule" type="WebApplication.MyModule, WebApplication" />
</modules>
</system.webServer><my.system.webServer>
<modules>
<moduleSettings name="MyModule">
<add key="Timeout" value="10" />
</moduleSettings>
</modules>
</my.system.webServer>
例外ハンドリングやキャッシュはまったく考えていませんが、次のようなコードを書けば実現できそうです。
using System;
using System.Configuration;
using System.Web;
using System.Web.Configuration;namespace WebApplication
{
public class ModulesSection : ConfigurationSection
{
[ConfigurationProperty("", IsDefaultCollection = true)]
[ConfigurationCollection(typeof(ModuleSettingCollection), AddItemName = "moduleSettings")]
public ModuleSettingCollection ModuleSettings
{
get
{
return (ModuleSettingCollection) base[""];
}
}
}public class ModuleSettingCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new KeyValueConfigurationCollection();
}protected override object GetElementKey(ConfigurationElement element)
{
return ((KeyValueConfigurationCollection) element).Name;
}public KeyValueConfigurationCollection Get(string name)
{
return (KeyValueConfigurationCollection) BaseGet(name);
}
}public class KeyValueConfigurationCollection : ConfigurationElementCollection
{
[ConfigurationProperty("name", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get
{
return (string) this["name"];
}
set
{
this["name"] = value;
}
}protected override ConfigurationElement CreateNewElement()
{
return new KeyValueConfigurationElement();
}protected override object GetElementKey(ConfigurationElement element)
{
return ((KeyValueConfigurationElement) element).Key;
}
}public class KeyValueConfigurationElement : ConfigurationElement
{
[ConfigurationProperty("key", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Key
{
get
{
return (string) this["key"];
}
set
{
this["key"] = value;
}
}[ConfigurationProperty("value", DefaultValue = "")]
public string Value
{
get
{
return (string) this["value"];
}
set
{
this["value"] = value;
}
}
}public abstract class ParamAwareModuleBase : IHttpModule
{
protected ParamAwareModuleBase()
{
}public virtual void Init(HttpApplication context)
{
var moduleName = GetModuleName(context);
var modulesSection = (ModulesSection) WebConfigurationManager.GetSection("my.system.webServer/modules");
var keyValueCollection = modulesSection.ModuleSettings.Get(moduleName);
foreach (KeyValueConfigurationElement element in keyValueCollection)
{
var property = GetType().GetProperty(element.Key);
if (property.CanWrite)
{
var value = Convert(property.PropertyType, element.Value);
property.SetValue(this, value, null);
}
}
}public virtual void Dispose()
{
}protected virtual string GetModuleName(HttpApplication context)
{
var moduels = context.Modules;
var count = moduels.Count;
for (var i = 0; i < count; i++)
{
var module = moduels.Get(i);
if (module == this)
{
return moduels.GetKey(i);
}
}
throw new InvalidOperationException("module not found.");
}protected virtual object Convert(Type type, string value)
{
if (type == typeof(int))
{
return System.Convert.ToInt32(value);
}
return value;
}
}public class MyModule : ParamAwareModuleBase
{
public int Timeout { get; private set; }public override void Init(HttpApplication context)
{
base.Init(context);
//...
}
}
}
こういう機能って標準ではないですよね?