Mos*_*ose 45 c# reflection code-generation assemblies stack-frame
Assembly.GetEntryAssembly()不适用于Web应用程序.
但是......我真的需要这样的东西.我使用了一些在Web和非Web应用程序中使用的深层嵌套代码.
我目前的解决方案是浏览StackTrace以找到第一个被调用的程序集.
/// <summary>
/// Version of 'GetEntryAssembly' that works with web applications
/// </summary>
/// <returns>The entry assembly, or the first called assembly in a web application</returns>
public static Assembly GetEntyAssembly()
{
// get the entry assembly
var result = Assembly.GetEntryAssembly();
// if none (ex: web application)
if (result == null)
{
// current method
MethodBase methodCurrent = null;
// number of frames to skip
int framestoSkip = 1;
// loop until we cannot got further in the stacktrace
do
{
// get the stack frame, skipping the given number of frames
StackFrame stackFrame = new StackFrame(framestoSkip);
// get the method
methodCurrent = stackFrame.GetMethod();
// if found
if ((methodCurrent != null)
// and if that method is not excluded from the stack trace
&& (methodCurrent.GetAttribute<ExcludeFromStackTraceAttribute>(false) == null))
{
// get its type
var typeCurrent = methodCurrent.DeclaringType;
// if valid
if (typeCurrent != typeof (RuntimeMethodHandle))
{
// get its assembly
var assembly = typeCurrent.Assembly;
// if valid
if (!assembly.GlobalAssemblyCache
&& !assembly.IsDynamic
&& (assembly.GetAttribute<System.CodeDom.Compiler.GeneratedCodeAttribute>() == null))
{
// then we found a valid assembly, get it as a candidate
result = assembly;
}
}
}
// increase number of frames to skip
framestoSkip++;
} // while we have a working method
while (methodCurrent != null);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
为了确保组装符合我们的要求,我们有三个条件:
我遇到的最后一个问题是何时在单独的程序集中定义基页.(我使用ASP.Net MVC,但ASP.Net也是如此).在这种特殊情况下,它是返回的单独程序集,而不是包含页面的程序集.
我现在正在寻找的是:
1)我的装配验证条件是否足够?(我可能已经忘记了案件)
2)从ASP.Net临时文件夹中的给定代码生成的程序集中,是否有一种方法可以获取有关包含该页面/视图的项目的信息?(我想不是,但谁知道......)
que*_*rin 51
这似乎是一种可靠,简单的方法来获取Web应用程序的"入口"或主要程序集.
如果你把控制器放在一个单独的项目中,你可能会发现ApplicationInstance的基类与包含Views的MVC项目不在同一个程序集中 - 但是,这个设置似乎很少见(我提到它因为我试过这个设置在一个点,一段时间后,一些博客支持这个想法).
static private Assembly GetWebEntryAssembly()
{
if (System.Web.HttpContext.Current == null ||
System.Web.HttpContext.Current.ApplicationInstance == null)
{
return null;
}
var type = System.Web.HttpContext.Current.ApplicationInstance.GetType();
while (type != null && type.Namespace == "ASP") {
type = type.BaseType;
}
return type == null ? null : type.Assembly;
}
Run Code Online (Sandbox Code Playgroud)
rob*_*rke 10
在我的情况下,我需要在初始化System.Web.HttpContext.Current.ApplicationInstance之前获取Web应用程序的"入口程序集".此外,我的代码需要适用于各种应用程序类型(窗口服务,桌面应用程序等),我不喜欢用Web问题污染我的常用代码.
我创建了一个自定义程序集级属性,可以在要指定为入口点程序集的程序集的AssembyInfo.cs文件中声明.然后,您只需调用属性的静态GetEntryAssembly方法来获取条目程序集.如果Assembly.GetEntryAssembly返回非null,则使用该null,否则它将在已加载的程序集中搜索具有custom属性的程序集.结果缓存在Lazy <T>中.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace EntryAssemblyAttributeDemo
{
/// <summary>
/// For certain types of apps, such as web apps, <see cref="Assembly.GetEntryAssembly"/>
/// returns null. With the <see cref="EntryAssemblyAttribute"/>, we can designate
/// an assembly as the entry assembly by creating an instance of this attribute,
/// typically in the AssemblyInfo.cs file.
/// <example>
/// [assembly: EntryAssembly]
/// </example>
/// </summary>
[AttributeUsage(AttributeTargets.Assembly)]
public sealed class EntryAssemblyAttribute : Attribute
{
/// <summary>
/// Lazily find the entry assembly.
/// </summary>
private static readonly Lazy<Assembly> EntryAssemblyLazy = new Lazy<Assembly>(GetEntryAssemblyLazily);
/// <summary>
/// Gets the entry assembly.
/// </summary>
/// <returns>The entry assembly.</returns>
public static Assembly GetEntryAssembly()
{
return EntryAssemblyLazy.Value;
}
/// <summary>
/// Invoked lazily to find the entry assembly. We want to cache this value as it may
/// be expensive to find.
/// </summary>
/// <returns>The entry assembly.</returns>
private static Assembly GetEntryAssemblyLazily()
{
return Assembly.GetEntryAssembly() ?? FindEntryAssemblyInCurrentAppDomain();
}
/// <summary>
/// Finds the entry assembly in the current app domain.
/// </summary>
/// <returns>The entry assembly.</returns>
private static Assembly FindEntryAssemblyInCurrentAppDomain()
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var entryAssemblies = new List<Assembly>();
foreach (var assembly in assemblies)
{
// Note the usage of LINQ SingleOrDefault. The EntryAssemblyAttribute's AttrinuteUsage
// only allows it to occur once per assembly; declaring it more than once results in
// a compiler error.
var attribute =
assembly.GetCustomAttributes().OfType<EntryAssemblyAttribute>().SingleOrDefault();
if (attribute != null)
{
entryAssemblies.Add(assembly);
}
}
// Note that we use LINQ Single to ensure we found one and only one assembly with the
// EntryAssemblyAttribute. The EntryAssemblyAttribute should only be put on one assembly
// per application.
return entryAssemblies.Single();
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
18390 次 |
最近记录: |