Я создал стандартную систему конфигурации для HttpModule, которая позволяет подключаемые инспекторы заголовков HTTP.Для справки вот базовая схема кода - этого должно быть достаточно, чтобы понять, что я делаю:
public interface IHttpHeaderInspectingAuthenticatorFactory<T>
where T: HttpHeaderInspectingAuthenticatorConfigurationElement
{
IHttpHeaderInspectingAuthenticator<T> Construct(T config);
}
public class BasicAuthenticationInspectingAuthenticatorFactory :
IHttpHeaderInspectingAuthenticator<BasicAuthenticationHeaderInspectorConfigurationElement>
{
public IHttpHeaderInspectingAuthenticator<BasicAuthenticationHeaderInspectorConfigurationElement> Construct(BasicAuthenticationHeaderInspectorConfigurationElement config)
{
return new BasicAuthenticationInspectingAuthenticator(config);
}
}
public class BasicAuthenticationInspectingAuthenticator : HttpHeaderInspectingAuthenticatorBase<BasicAuthenticationHeaderInspectorConfigurationElement>
{
internal BasicAuthenticationInspectingAuthenticator(BasicAuthenticationHeaderInspectorConfigurationElement config)
: base(config) {}
//snip -- IHttpHeaderInspectingAuthenticator<T> and IHttpHeaderInspectingAuthenticator implementation
}
public class BasicAuthenticationHeaderInspectorConfigurationElement : HttpHeaderInspectingAuthenticatorConfigurationElement
{
//extra properties
}
public class HttpHeaderInspectingAuthenticatorConfigurationElement : ConfigurationElement
{
protected override void PostDeserialize()
{
base.PostDeserialize();
//simple verification of info supplied in config
var t = Type.GetType(Factory);
if (null == t)
throw new ConfigurationErrorsException(String.Format("The factory type specified [{0}] cannot be found - check configuration settings", Factory ?? ""));
if (!typeof(IHttpHeaderInspectingAuthenticatorFactory<>).IsGenericInterfaceAssignableFrom(t))
throw new ConfigurationErrorsException(String.Format("The factory type specified [{0}] must derive from {1} - check configuration settings", Factory ?? "", typeof(IHttpHeaderInspectingAuthenticatorFactory<>).Name));
var c = t.GetConstructor(Type.EmptyTypes);
if (null == c)
throw new ConfigurationErrorsException(String.Format("The factory type specified [{0}] must have a parameterless constructor - check configuration settings", Factory ?? ""));
}
[ConfigurationProperty("factory", IsRequired = true)]
public string Factory
{
get { return (string)this["factory"]; }
set { this["factory"] = value; }
}
//this allows us to use types derived from HttpHeaderInspectingAuthenticatorConfigurationElement
protected override bool OnDeserializeUnrecognizedAttribute(string name, string value)
{
ConfigurationProperty property = new ConfigurationProperty(name, typeof(string), value);
Properties.Add(property);
base[property] = value;
return true;
}
public IHttpHeaderInspectingAuthenticator GetInspector()
{
dynamic factoryInstance = Activator.CreateInstance(Type.GetType(Factory));
return factoryInstance.Construct(this);
}
}
Теперь проблема возникает в вызове GetInspector - все экземплярыпредоставленное имя фабрики должно реализовывать IHttpHeaderInspectingAuthenticatorFactor <> (как указано в PostDeserialize).Следовательно, все они будут иметь метод Construct, где предоставленный тип T будет фактически фактическим типом класса, реализующего метод GetInspector ().Так, например, GetInspector будет вызываться для экземпляра BasicAuthenticationHeaderInspectorConfigurationElement - поэтому 'this' будет экземпляром BasicAuthenticationHeaderInspectorConfigurationElement.
Однако вызов Construct завершается неудачно.Он находит метод в порядке, но, видимо, тип параметра НЕ совпадает в зависимости от выданного исключения RuntimeBinderException.На основании CallSite.Target может показаться, что ожидаемый тип, который ожидает динамический прокси-сервер, - это HttpHeaderInspectingAuthenticatorConfigurationElement - передаваемый «this» - это BasicAuthenticationHeaderInspectorConfigurationElement, полученный из этой базы.
Так что же дает?Я не получаю что-то здесь?Я попытался передать (это как динамическое) или ((HttpHeaderInspectingAuthenticatorConfigurationElement) это) - но оба не удаются с одной и той же проблемой.
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The best overloaded method match for 'Redcated.Authentication.BasicAuthenticationInspectingAuthenticatorFactory.Construct(Redcated.Authentication.Configuration.BasicAuthenticationHeaderInspectorConfigurationElement)' has some invalid arguments
at CallSite.Target(Closure , CallSite , Object , HttpHeaderInspectingAuthenticatorConfigurationElement )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at Redcated.Authentication.Configuration.HttpHeaderInspectingAuthenticatorConfigurationElement.GetInspector() in D:\Users\ebrown\Documents\Visual Studio 2010\Projects\Utility\source\Authentication Library\Configuration\HttpHeaderInspectingAuthenticatorConfigurationElement.cs:line 79
at Redcated.Authentication.Configuration.HttpHeaderInspectingAuthenticatorConfigurationElementCollection.<GetInspectors>b__0(HttpHeaderInspectingAuthenticatorConfigurationElement i) in D:\Users\ebrown\Documents\Visual Studio 2010\Projects\Utility\source\Authentication Library\Configuration\HttpHeaderInspectingAuthenticatorConfigurationElementCollection.cs:line 78
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
at Redcated.Authentication.HttpHeaderInspectingAuthenticationModule.AuthenticateRequest(Object sender, EventArgs e) in D:\Users\ebrown\Documents\Visual Studio 2010\Projects\Utility\source\Authentication Library\HttpHeaderInspectingAuthenticationModule.cs:line 49
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
FYI - я обошел эту проблему, изменив архитектуру интерфейсовнемного:
public interface IHttpHeaderInspectingAuthenticatorFactory
{
IHttpHeaderInspectingAuthenticator Construct(HttpHeaderInspectingAuthenticatorConfigurationElement config);
}
public interface IHttpHeaderInspectingAuthenticatorFactory<T> : IHttpHeaderInspectingAuthenticatorFactory
where T: HttpHeaderInspectingAuthenticatorConfigurationElement
{
IHttpHeaderInspectingAuthenticator<T> Construct(T config);
}
public abstract class HttpHeaderInspectingAuthenticatorFactoryBase<T> : IHttpHeaderInspectingAuthenticatorFactory<T>
where T : HttpHeaderInspectingAuthenticatorConfigurationElement
{
protected static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public abstract IHttpHeaderInspectingAuthenticator<T> Construct(T config);
public IHttpHeaderInspectingAuthenticator Construct(HttpHeaderInspectingAuthenticatorConfigurationElement config)
{
return Construct((T)config);
}
}
public class BasicAuthenticationInspectingAuthenticatorFactory :
HttpHeaderInspectingAuthenticatorFactoryBase<BasicAuthenticationHeaderInspectorConfigurationElement>
{
public override IHttpHeaderInspectingAuthenticator<BasicAuthenticationHeaderInspectorConfigurationElement> Construct(BasicAuthenticationHeaderInspectorConfigurationElement config)
{
return new BasicAuthenticationInspectingAuthenticator(config);
}
}
И затем, конечно, вызов GetInspector становится
public IHttpHeaderInspectingAuthenticator GetInspector()
{
var factoryInstance = (IHttpHeaderInspectingAuthenticatorFactory)Activator.CreateInstance(Type.GetType(Factory));
return factoryInstance.Construct(this);
}
Так что я предполагаю, что в моем понимании здесь должно быть упущение ... надеясь, что кто-то может потерятьсвет.
Спасибо!