ASP.NET MVC のソース コードをざっと見てみたところ、何かが初めてキャッシュ ファイルを読み取ろうとしたときに、キャッシュ ファイルが作成されることがわかりました。これは通常、アプリケーションの開始時に発生します。
ControllerTypeCache
ASP.NET MVC には、ファイル名を含む定数文字列を持つ内部クラスが含まれています。ソース コードで「MVC-ControllerTypeCache.xml」が出現するのはこれだけです。
internal sealed class ControllerTypeCache
{
private const string TypeCacheName = "MVC-ControllerTypeCache.xml";
...
}
この定数は、ControllerTypeCache
クラスのこのメソッドでのみ使用されます。
public void EnsureInitialized(IBuildManager buildManager)
{
if (_cache == null)
{
lock (_lockObj)
{
if (_cache == null)
{
List<Type> controllerTypes = TypeCacheUtil.GetFilteredTypesFromAssemblies(TypeCacheName, IsControllerType, buildManager);
var groupedByName = controllerTypes.GroupBy(
t => t.Name.Substring(0, t.Name.Length - "Controller".Length),
StringComparer.OrdinalIgnoreCase);
_cache = groupedByName.ToDictionary(
g => g.Key,
g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
StringComparer.OrdinalIgnoreCase);
}
}
}
}
にファイル名が渡されていることがわかりますTypeCacheUtil.GetFilteresTypesFromAssemblies
。これはそのメソッドがどのように見えるかです:
public static List<Type> GetFilteredTypesFromAssemblies(string cacheName, Predicate<Type> predicate, IBuildManager buildManager)
{
TypeCacheSerializer serializer = new TypeCacheSerializer();
// first, try reading from the cache on disk
List<Type> matchingTypes = ReadTypesFromCache(cacheName, predicate, buildManager, serializer);
if (matchingTypes != null)
{
return matchingTypes;
}
// if reading from the cache failed, enumerate over every assembly looking for a matching type
matchingTypes = FilterTypesInAssemblies(buildManager, predicate).ToList();
// finally, save the cache back to disk
SaveTypesToCache(cacheName, matchingTypes, buildManager, serializer);
return matchingTypes;
}
ご覧のとおり、キャッシュ ファイルから読み取ろうとします。読み取りが失敗した場合 (ファイルがまだ存在しないなどの理由で)、controllertypes の新しいリストが生成され、新しいバージョンのキャッシュ ファイルに保存されます。
メソッドは次のReadTypesFromCache
ようになります。
internal static List<Type> ReadTypesFromCache(string cacheName, Predicate<Type> predicate, IBuildManager buildManager, TypeCacheSerializer serializer)
{
try
{
Stream stream = buildManager.ReadCachedFile(cacheName);
if (stream != null)
{
using (StreamReader reader = new StreamReader(stream))
{
List<Type> deserializedTypes = serializer.DeserializeTypes(reader);
if (deserializedTypes != null && deserializedTypes.All(type => TypeIsPublicClass(type) && predicate(type)))
{
// If all read types still match the predicate, success!
return deserializedTypes;
}
}
}
}
catch
{
}
return null;
}
ご覧のとおり、 a を使用しBuildManager
てキャッシュされたファイルを読み取ります。
これは、キャッシュ ファイルを読み取ったり作成したりすることができる唯一の場所です。呼び出し階層をナビゲートすると、DefaultControllerFactory
クラスまたはクラスのいずれかからそのメソッドに行き着きAreaRegistration
ます。
したがって、これらのクラスのいずれかがアプリケーションでコントローラーのリストを初めて必要とするときGetFilteredTypesFromAssemblies
に、クラスのメソッドTypeCacheUtil
が呼び出されることになると思います。ファイルを読み取れない場合にのみ、キャッシュ ファイルを生成します。このクラスは aBuildManager
を使用して読み取るため、ファイルが破損している、見つからない、またはアプリケーションが再起動されたときにのみ生成されると思います。
Web を閲覧した後、MVC-ControllerTypeCache.xml ファイルを再生成するには、再起動をトリガーするために Global.asax または Web.Config ファイルを変更して保存するなどの方法でうまくいくと報告しているようです。
独自のコードでこのファイルを利用できますか? おそらくできますが、そうすべきではありません。リフレクションを使用するだけです。そのアプローチが原因でパフォーマンスの問題に直面したことがある場合は、キャッシングについて考え始めることができます。その場合、独自のシリアル化されたコントローラーのリストを作成し、.NET の組み込みのキャッシング メカニズムを使用してキャッシュする方が「安全」だと思います。 MVC-ControllerTypeCache.xml を再利用しようとするのではなく、それらを使用してください。それは私が推測する理由で内部です。