Доступ к информации в AssemblyInfo.cs с помощью Reflection на веб-сайте - PullRequest
3 голосов
/ 17 апреля 2009

Я создал DLL, которая будет собирать информацию из AssemblyInfo.cs. В конструкторе класса я использую Reflection, чтобы получить самое работающее приложение.

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

Как это предполагается использовать, если я вызываю это из любой библиотеки DLL в данном приложении, MyApp, которая позволяет сказать, что имя всегда будет «MyApp». Получение этой информации не является проблемой, и она прекрасно работает в Windows Services и Windows Applications. У меня вопрос такой: Как мне получить сборку самого верхнего сайта?

Я нашел несколько статей и могу получить информацию в Global.asax.cs, переместив AssemblyInfo.cs для веб-сайта из папки App_Code в корень веб-сайта. Затем, добавив параметр 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">

Используя это, я могу получить информацию в AssemblyInfo.cs для Веб-сайта через System.Reflection.Assembly.GetExecutingAssembly(). Теперь я могу перегрузить конструктор моего AppInfo класса, чтобы принять Assembly и получить информацию таким образом, но если другая DLL, используемая MyWebSite, создаст new AppInfo(), я получу вместо этого информацию о сборке этой DLL родительского сайта.

Я знаю, что если бы я работал с веб-приложениями, а не с веб-сайтами, у меня не было бы этой проблемы, но по причинам, в которые я не буду вдаваться, я не смогу использовать веб-приложения. Любые предложения о том, как я могу прочитать информацию из AssemblyInfo.cs веб-сайта, на котором я работаю, независимо от того, в какой DLL я нахожусь?

РЕДАКТИРОВАТЬ: Мне это нужно для работы с веб-сайтами, приложениями Windows и службами Windows

Ответы [ 4 ]

2 голосов
/ 27 апреля 2009

Если я правильно вас понимаю, проблема в том, что 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 голос
/ 28 апреля 2009

Девиант прав. Но если вы можете, вы должны использовать Assembly.Load вместо Assembly.LoadFile.

Вот хорошая ссылка:

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

1 голос
/ 27 апреля 2009

Домены приложений создаются для каждого веб-сайта, а затем файлы bin * .dll загружаются в домен приложений этого Приложения. На сайте нет «Мастерской сборки», по крайней мере, любой, которая имеет какое-то особое значение.

Это процесс. System.Web.Hosting.ProcessHost , который создает System.Web.ApplicationHost посредством комбинации System.Web.Hosting.ApplicationManger и System .Web.Hosting.Environment , который затем создает System.AppDomain для приложения.

AppDomain защищен довольно хорошо, поэтому, если вы не знаете, как попасть в AppDomain, вам не повезло.

Если вы сможете обновить свой вопрос, возможно, кто-то сможет вам помочь.

Вы МОЖЕТЕ быть в состоянии сделать это, если безопасность не настроена должным образом "

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 голосов
/ 24 января 2011

Используя предложение Alconja, я проверял сборку. 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...