3 Stimmen

Zugriff auf Informationen in der Datei AssemblyInfo.cs mit Reflection in einer Website

Ich habe eine DLL erstellt, die Informationen aus der AssemblyInfo.cs sammeln wird. Im Klassenkonstruktor verwende ich Reflection, um die oberste laufende Anwendung zu ermitteln.

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
    }
}

Wenn ich dies von einer beliebigen DLL in einer bestimmten Anwendung, MyApp, aufrufe, wird der Name immer "MyApp" lauten, so wie dies beabsichtigt ist. Das Abrufen dieser Informationen ist kein Problem, und es funktioniert hervorragend in Windows-Diensten und Windows-Anwendungen. Meine Frage ist nun folgende: Wie erhalte ich die Versammlung der obersten Website?

Ich habe ein paar Artikel gefunden, und ich kann die Informationen in der Global.asax.cs erhalten, indem ich die AssemblyInfo.cs für die Website aus dem Ordner App_Code in den Stamm der Website verschiebe. Dann durch Hinzufügen einer CompilerOption zum physischen Pfad der 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">

Damit kann ich Informationen in der AssemblyInfo.cs für die Website abrufen durch System.Reflection.Assembly.GetExecutingAssembly() . Jetzt kann ich den Konstruktor meiner AppInfo Klasse zu akzeptieren Assembly und auf diese Weise Informationen abrufen, aber wenn eine andere DLL, die von MyWebSite erstellt eine new AppInfo() Ich erhalte die Assembly-Informationen dieser DLL anstelle der übergeordneten Website.

Ich weiß, dass ich dieses Problem nicht hätte, wenn ich mit Web Apps statt mit Websites arbeiten würde, aber aus Gründen, die ich nicht näher erläutern möchte, kann ich keine Web Apps verwenden. Irgendwelche Vorschläge, wie ich Informationen aus der AssemblyInfo.cs der Website lesen kann, die ich in egal welcher DLL ich bin?

EDITAR: Ich benötige diese Funktion für Websites, Windows-Anwendungen und Windows-Dienste

2voto

Alconja Punkte 14686

Wenn ich Sie richtig verstehe, besteht das Problem darin, dass Assembly.GetEntryAssembly() in einer Website null zurückgibt und Assembly.GetCallingAssembly() gibt das Falsche zurück, weil Sie eine Kette von Aufrufen haben, die dazu führen, dass die Website nicht der unmittelbare Aufrufer ist. Wenn das der Fall ist, können Sie die "Entry Assembly" mit Hilfe der Stapelverfolgung finden und die aufrufenden Frames zurückverfolgen. Der Stack wird voller Verweise von System.Web usw. sein, da der Aufruf irgendwo tief im IIS erfolgt ist, aber Sie sollten in der Lage sein, die Assembly herauszufinden, an der Sie interessiert sind, indem Sie den niedrigsten Frame nehmen, den Sie eindeutig als zu Ihnen gehörend identifizieren können. Beachten Sie, dass dies ziemlich umständlich ist, aber ich denke, dass Sie damit das bekommen, was Sie wollen...

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;
   }
}

Hoffentlich findet jemand anderes eine weniger unangenehme Lösung... aber wenn Sie wirklich nicht weiterkommen, könnte das hier helfen.

1voto

Chad Grant Punkte 41992

AppDomains werden pro Website erstellt und die bin*.dll-Dateien werden in die AppDomain der Anwendung geladen. Es gibt keine "Master Assembly" der Website, zumindest keine, die eine besondere Bedeutung hat.

Es ist ein Prozess. System.Web.Hosting.ProcessHost die eine System.Web.ApplicationHost durch eine Kombination der System.Web.Hosting.ApplicationManger y System.Web.Hosting.Umgebung die dann eine System.AppDomain für die Anwendung erstellt.

AppDomain ist ziemlich gut gesichert. Wenn Sie also nicht wissen, wie Sie in eine AppDomain eindringen können, haben Sie Pech.

Wenn Sie Ihre Frage aktualisieren können, kann Ihnen vielleicht jemand weiterhelfen.

Sie MAI nicht in der Lage sein, dies zu tun, wenn die Sicherheit nicht ordnungsgemäß eingerichtet ist.

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));
    }
}

Sie gehen hier davon aus, dass die Master-Site nicht kompiliert ist (ein App_Code-Verzeichnis hat) und sich im gleichen Anwendungspool wie Ihre Child-Site befindet. Haben Sie den nötigen Zugriff, um dies zu tun? Handelt es sich bei der Master-Site um eine gemeinsam genutzte Hosting-Site oder ähnliches?

1voto

Lucas Punkte 339

Deviant hat Recht. Aber wenn Sie können, sollten Sie Assembly.Load anstelle von Assembly.LoadFile verwenden.

Hier ist eine schöne Referenz:

http://gisresearch.blogspot.com/2007/09/assembly-load-loadfrom-loadfile.html

0voto

PepitoSh Punkte 1765

Mit Alconjas Vorschlag habe ich nach assembly.GlobalAssemblyCache gesucht, bis ich die erste gefunden habe, die da ist. Die letzte, die nicht vorhanden ist, ist die erste meiner eigenen DLLs, die ich als Einstiegs-Assembly betrachte.

Die folgende Klasse hilft, ein Type-Objekt zu erhalten, wenn nur der Name der Baugruppe und der Name des Typs bekannt sind.

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);
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X