ASPを知っておく必要がありますNET知識------動的登録httpmoduleについて(トムおじさんにはかなわない)

20675 ワード

一、動的登録に関する問題


多くの人がトムおじさんのMVC以前の件シリーズ(6):動的登録HttpModuleを見たことがあります
実はトムおじさんはhttpmoduleの動的登録の根本的なメカニズムがどこにあるかを発見しなかった.
つまり、どのように動的に登録しますか?なぜ動的に登録できるのですか?
トムおじさんは次のように書いた.
前の章では、HttpApplicationが初期化時にすべてのプロファイルに登録されているHttpModulesを初期化することを知っていますが、Webからだけでなく、初期化前にHttpModuleを動的にロードできるかどうか疑問があります。configで読み込みますか? 答えは肯定的だASP.NET MVC 3がリリースされたときにMicrosoftが提供されました。Web.Infrastructure.dllファイル、このファイルはHttpModuleを動的に登録する機能を提供していますが、どのように登録していますか?まずMVC 3のソースコードに行って、このDLLのソースコードを見てみましょう。

実はhttpmodule動的登録はASP.NETフレーム内で独自に提供する仕組みは、MVCとは関係なく、つまりMVCがあるかどうか、ASP.NET自身もこのメカニズムを提供しています(他の研究はありません
.NETバージョン、少なくとも.NET 4.5ではそうですが、MVCフレームを含まない場合です)

二、httpmoduleの初期化について


次の章では、次のコードで振り返ります.
// System.Web.HttpApplication
internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)
{
    this._state = state;
    PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);
    try
    {
        try
        {
            this._initContext = context;
            this._initContext.ApplicationInstance = this;
            context.ConfigurationPath = context.Request.ApplicationPathObject;
            using (new DisposableHttpContextWrapper(context))
            {
                if (HttpRuntime.UseIntegratedPipeline)
                {
                    try
                    {
                        context.HideRequestResponse = true;
                        this._hideRequestResponse = true;
                        this.InitIntegratedModules();
                        goto IL_6B;
                    }
                    finally
                    {
                        context.HideRequestResponse = false;
                        this._hideRequestResponse = false;
                    }
                }
                this.InitModules();//    ,         module,                 
                IL_6B:
                if (handlers != null)
                {
                    this.HookupEventHandlersForApplicationAndModules(handlers);
                }
                this._context = context;
                if (HttpRuntime.UseIntegratedPipeline && this._context != null)
                {
                    this._context.HideRequestResponse = true;
                }
                this._hideRequestResponse = true;
                try
                {
                    this.Init();
                }
                catch (Exception error)
                {
                    this.RecordError(error);
                }
            }
            if (HttpRuntime.UseIntegratedPipeline && this._context != null)
            {
                this._context.HideRequestResponse = false;
            }
            this._hideRequestResponse = false;
            this._context = null;
            this._resumeStepsWaitCallback = new WaitCallback(this.ResumeStepsWaitCallback);
            if (HttpRuntime.UseIntegratedPipeline)
            {
                this._stepManager = new HttpApplication.PipelineStepManager(this);
            }
            else
            {
                this._stepManager = new HttpApplication.ApplicationStepManager(this);
            }
            this._stepManager.BuildSteps(this._resumeStepsWaitCallback);
        }
        finally
        {
            this._initInternalCompleted = true;
            context.ConfigurationPath = null;
            this._initContext.ApplicationInstance = null;
            this._initContext = null;
        }
    }
    catch
    {
        throw;
    }
}

 
private void InitModules()
{
    HttpModulesSection httpModules = RuntimeConfig.GetAppConfig().HttpModules;//      
    HttpModuleCollection httpModuleCollection = httpModules.CreateModules();//     
    HttpModuleCollection other = this.CreateDynamicModules();
    httpModuleCollection.AppendCollection(other);
    this._moduleCollection = httpModuleCollection;
    this.InitModulesCommon();
}
private HttpModuleCollection CreateDynamicModules()
{
    HttpModuleCollection httpModuleCollection = new HttpModuleCollection();
    foreach (DynamicModuleRegistryEntry current in HttpApplication._dynamicModuleRegistry.LockAndFetchList())
    {
        HttpModuleAction httpModuleAction = new HttpModuleAction(current.Name, current.Type);
     // module httpModuleCollection.AddModule(httpModuleAction.Entry.ModuleName, httpModuleAction.Entry.Create()); }
return httpModuleCollection;// this._moduleCollection }

最後にthisを呼び出す場所が想像できます.moduleCollectionは初期化操作を得ることができる.実際には、ここで各moduleの初期化操作を行います.
private void InitModulesCommon()
        {
            int count = this._moduleCollection.Count;
            for (int i = 0; i < count; i++)
            {
                this._currentModuleCollectionKey = this._moduleCollection.GetKey(i);
                this._moduleCollection[i].Init(this);//           httpmodule      
            }
            this._currentModuleCollectionKey = null;
            this.InitAppLevelCulture();
        }

でも、これ
this._moduleCollection

集合したデータも
HttpApplication._dynamicModuleRegistry.LockAndFetchList()

public ICollectionLockAndFetchList()は、ここのデータに動的に登録されているmoduleが含まれている場合、
動的登録の目的を達成しました
public ICollection<DynamicModuleRegistryEntry> LockAndFetchList()
        {
            ICollection<DynamicModuleRegistryEntry> entries;
            lock (this._lockObj)
            {
                this._entriesReadonly = true;
                entries = this._entries;// :       _entries       module     
            }
            return entries;
        }

たまたまhttpapplicationではmoduleを登録する方法があり、多くの人が使ったことがないと思います
public static void RegisterModule(Type moduleType)
        {
            RuntimeConfig appConfig = RuntimeConfig.GetAppConfig();
            HttpRuntimeSection httpRuntime = appConfig.HttpRuntime;
            if (httpRuntime.AllowDynamicModuleRegistration)
            {
                HttpApplication.RegisterModuleInternal(moduleType); return;
            }
            throw new InvalidOperationException(SR.GetString("DynamicModuleRegistrationOff"));
        }
internal static void RegisterModuleInternal(Type moduleType)
        {
            HttpApplication._dynamicModuleRegistry.Add(moduleType);//   ,                  .
        }

 
public void Add(Type moduleType)
        {
            if (moduleType == null)
            {
                throw new ArgumentNullException("moduleType");
            }
            if (!typeof(IHttpModule).IsAssignableFrom(moduleType))
            {
                string message = string.Format(CultureInfo.CurrentCulture, SR.GetString("DynamicModuleRegistry_TypeIsNotIHttpModule"), new object[]
                {
                    moduleType
                });
                throw new ArgumentException(message, "moduleType");
            }
            lock (this._lockObj)
            {
                if (this._entriesReadonly)
                {
                    throw new InvalidOperationException(SR.GetString("DynamicModuleRegistry_ModulesAlreadyInitialized"));
                }
                this._entries.Add(new DynamicModuleRegistryEntry(DynamicModuleRegistry.MakeUniqueModuleName(moduleType), moduleType.AssemblyQualifiedName));
            }
        }

ちょうどそのメカニズムが重なる、すなわち動的登録の効果はここに由来する.
this._entries.Add

しかし、実際には、httpapplicationのRegisterModuleメソッドを純粋に呼び出すと目的が達成されないことがわかります.例えば、Globalファイルに次のコードを追加します.
public Global()
        {
            //DynamicModuleRegistry
             HttpApplication.RegisterModule(typeof(CustomModule));
            InitializeComponent();   
            
        }

システム放出異常:
  行26: { 行27: //DynamicModuleRegistry 行28: HttpApplication.RegisterModule(typeof(CustomModule)); 行29: InitializeComponent(); 行30: ソースファイル:c:UsersqscqDocumentsSharpDevelop ProjectsASPNET_ST_1\ASPNET_ST_1\Global.asax.cs行:28

これはなぜですか.
異常の原因は
システムでWeb.DynamicModuleRegistry.Add(Type moduleType) public void Add(Type moduleType) { if (moduleType == null) { throw new ArgumentNullException("moduleType"); } if (!typeof(IHttpModule).IsAssignableFrom(moduleType)) { string message = string.Format(CultureInfo.CurrentCulture, SR.GetString("DynamicModuleRegistry_TypeIsNotIHttpModule"), new object[] { moduleType }); throw new ArgumentException(message, "moduleType"); } lock (this._lockObj) { if (this._entriesReadonly) { throw new InvalidOperationException(SR.GetString("DynamicModuleRegistry_ModulesAlreadyInitialized")); } this._entries.Add(new DynamicModuleRegistryEntry(DynamicModuleRegistry.MakeUniqueModuleName(moduleType), moduleType.AssemblyQualifiedName)); } }  

つまり、_entriesReadonlyは今ではtrueです.つまり、そのtrueの前にmoduleを加えると問題ありません.では、いつtrueになったのでしょうか.実は前述のhttpapplicationが自分で初期化するとき、つまりInitModulesメソッドの中で.つまり、システムがメソッドを呼び出す前に呼び出す必要があります.
HttpApplication.RegisterModuleメソッドでいいです.

三、まとめ


前述のように、システムは自らHttpApplicationを呼び出した.RegisterModuleは、このメソッドを呼び出す前に、moduleを動的に登録することができます.
トムおじさんがくれた
[assembly: PreApplicationStartMethod(typeof(WebApplication1.Test.PreApplicationStartCode), "PreStart")]

 
この方法は明らかに目標を達成することができる.しかし、私たちは直接もっと簡単に来ることができます.直接Globalに静的構造関数を追加します.
次のようになります.
static   Global(){
            HttpApplication.RegisterModule(typeof(CustomModule));
         
}

   

四、感謝


数日来皆さんの関心に感謝して、私は引き続き書くことができて、兄台、推薦を求めて、関心を求めます.
大きな贈り物、みんなはよく見ることができて、みんなの支持に報いることができます