2009-04-16 59 views
3

我创建了一个将从AssemblyInfo.cs中收集信息的DLL。在类构造函数中,我使用Reflection来获取正在运行的最顶级应用程序。在网站中使用反射访问AssemblyInfo.cs中的信息

public class AppInfo() 
{ 
    public AppInfo() 
    { 
     System.Reflection.Assembly assembly = 
      System.Reflection.Assembly.GetEntryAssembly(); 
     if (assembly == null) 
      assembly = System.Reflection.Assembly.GetCallingAssembly(); 


     //code to gather needed information 
    } 
} 

这是怎么打算用来是,如果我在一个给定的应用,MyApp的调用这个来自任何DLL,让说这个名字将永远是“MyApp的”。检索该信息不是问题,它在Windows服务和Windows应用程序中运行良好。我的问题是: 如何获得最顶级网站的大会?

我发现了一些文章,我可以通过将AssemblyInfo.cs移出App_Code文件夹并进入网站根目录来获取Global.asax.cs中的信息。然后通过添加compilerOption到AssemblyInfo.cs中

<compiler 
language="c#;cs;csharp" 
extension=".cs" 
compilerOptions="C:\Sandbox\MyWebSite\AssemblyInfo.cs" 
type="Microsoft.CSharp.CSharpCodeProvider,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4"> 

使用,我能够通过System.Reflection.Assembly.GetExecutingAssembly()来检索的AssemblyInfo.cs对网站信息的物理路径。现在我可以重载我的AppInfo类的构造函数来接受Assembly并以这种方式检索信息,但如果另一个由MyWebSite使用的DLL创建了new AppInfo(),我将获得该DLL的程序集信息,而不是父网站。

我知道如果我正在使用网络应用程序而不是网站,我不会遇到这个问题,但出于我不会涉足的原因,我无法使用网络应用程序。任何关于如何从我运行的网站的AssemblyInfo.cs中读取信息的建议,无论我在哪个DLL中?

编辑:我需要这为网站时,Windows应用程序和Windows服务工作

+0

你怎么区分自己的“最高”的应用程序? – 2009-04-16 21:15:51

+0

对于使用Assembly.GetEntryAssembly()的应用程序,返回“最高”应用程序。在网站上,Assembly.GetEntryAssembly()的值为null,如果从网站本身调用,Assembly.GetCallingAssembly()是AppInfo的DLL,而不是我需要的网站。 – 2009-04-16 21:24:20

+0

你有权访问预编译的dll吗? – 2009-04-18 08:25:56

回答

2

如果我理解你正确,问题是Assembly.GetEntryAssembly()返回一个网站零和Assembly.GetCallingAssembly()将返回错误的事情,因为你有一连串的通话导致该网站不是直接呼叫者。如果是这样的话,您可以使用堆栈跟踪&找回调用帧的“Entry Assembly”。该堆栈将充满来自System.Web等的引用,因为调用将从IIS内部深处发起,但您应该能够通过抓取可以肯定识别的最低帧挑选出您感兴趣的程序集属于你。请注意,这是相当哈克,但我认为它会得到你想要的东西......

var trace = new StackTrace(); 
Assembly entryAssembly = null; 
foreach (var frame in trace.GetFrames()) 
{ 
    var assembly = frame.GetMethod().DeclaringType.Assembly; 
    //check if the assembly is one you own & therefore could be your logical 
    //"entry assembly". You could do this by checking the prefix of the 
    //Assembly Name if you use some standardised naming convention, or perhaps 
    //looking at the AssemblyCompanyAttribute, etc 
    if ("assembly is one of mine") 
    { 
     entryAssembly = assembly; 
    } 
} 

希望别人将能够拿出这样做的不太讨厌的方式...但如果你真的被卡住了,这可能会有所帮助。

1

AppDomain根据网站创建,然后将bin * .dll文件加载到该应用程序的AppDomain中。没有该网站的“大会”,至少有任何具有特殊意义的内容。

这是一个过程。 System.Web.Hosting.ProcessHost,它通过System.Web.Hosting.ApplicationMangerSystem.Web.Hosting.Environment的组合创建System.Web.ApplicationHost,然后为该应用程序创建一个System.AppDomain。

AppDomain非常安全,所以除非你知道如何进入AppDomain,否则你运气不好。

如果你可以更新你的问题,有人可能会帮助更多。

MAY能够做到这一点,如果安全性未正确设置”

String binDir = Server.MapPath("/bin/"); 
Response.Write(String.Format("Bin dir:{0}<br/><br/>",binDir)); 

foreach (string file in Directory.GetFiles(binDir, "*.dll")) 
{ 
    Response.Write(String.Format("File:{0}<br/>", file)); 
    try 
    { 
     Assembly assembly = Assembly.LoadFile(file); 
     object[] attrinutes = assembly.GetCustomAttributes(true); 
     foreach (var o in attrinutes) 
     { 
      //AssemblyCompanyAttribute is set in the AssemblyInfo.cs 
      if (o is AssemblyCompanyAttribute) 
      { 
       Response.Write(String.Format("Company Attribute: Company = {0}<br/>", ((AssemblyCompanyAttribute)o).Company)); 
       continue; 
      } 
      Response.Write(String.Format("Attribute: {0}<br/>", o)); 
     } 
    } 
    catch(Exception ex) 
    { 
     Response.Write(String.Format("Exception Reading File: {0} Exception: {1}",file,ex)); 
    } 
} 

我们假定你是很多在这里,主站点未编译(有一个App_Code目录),并驻留在同一应用程序池作为您的子站点您是否需要访问来执行此操作?主站点是共享托管站点吗?

0

使用Alconja的建议我检查assembly.GlobalAssemblyCache,直到我找到的第一个在那里。最后一个不在那里的是我认为入门程序集的第一个自己的dll。

如果只知道程序集名称和类型名称,则下面的类有助于获取Type对象。

public static class AssemblyHandler { 

    private static Dictionary<String, Assembly> Assemblies; 

    public static Assembly GetAssembly(String Name) { 

     if (Assemblies == null) { 
      Assemblies = new Dictionary<string, Assembly>(); 
      var mainAsm = Assembly.GetEntryAssembly(); 

      if (mainAsm == null) { 
       var trace = new StackTrace(); 
       foreach (var frame in trace.GetFrames()) { 
        var assembly = frame.GetMethod().DeclaringType.Assembly; 
        if (assembly.GlobalAssemblyCache) { 
         break; 
        } 
        mainAsm = assembly; 
       } 
      } 

      Assemblies.Add(mainAsm.FullName, mainAsm); 
      ScanReferencedAssemblies(mainAsm); 
     } 

     if (!Assemblies.ContainsKey(Name)) { 
      return null; 
     } 
     return Assemblies[Name]; 
    } 

    private static void ScanReferencedAssemblies(Assembly Asm) { 

     foreach (var refAsmName in Asm.GetReferencedAssemblies()) { 
      Assembly a = Assembly.Load(refAsmName); 
      if (a.GlobalAssemblyCache) { 
       continue; 
      } 
      if (!Assemblies.ContainsKey(a.FullName)) { 
       Assemblies.Add(a.FullName, a); 
       ScanReferencedAssemblies(a); 
      } 
     } 
    } 

    public static Type GetType(string AssemblyName, string TypeName) { 

     return GetAssembly(AssemblyName).GetType(TypeName); 
    } 
}