web-dev-qa-db-ja.com

C#呼び出し元アセンブリの親アセンブリ名を取得する

私が取り組んでいるC#単体テストアプリケーションがあります。関係するアセンブリは3つあります。C#アプリ自体のアセンブリ、アプリが使用する2番目のアセンブリ、2番目のアセンブリが使用する3番目のアセンブリです。

したがって、呼び出しは次のようになります。

First Assembly ------> Second Assembly---------> Third Assembly.

私が3番目の議会で行う必要があるのは、2番目の議会を呼び出した第1議会の名前を取得することです。

Assembly.GetExecutingAssembly().ManifestModule.Name
Assembly.GetCallingAssembly().ManifestModule.Name

2番目のアセンブリの名前を返します。そして

Assembly.GetEntryAssembly().ManifestModule.Name

nULLを返す

最初のアセンブリのアセンブリ名に到達する方法があるかどうか誰かが知っていますか?

他のユーザーの要望に応じて、ここにコードを追加しました。これは100%コードではありませんが、このようなコードに従ってください。

namespace FirstAssembly{
public static xcass A
{
        public static Stream OpenResource(string name)
        {
            return Reader.OpenResource(Assembly.GetCallingAssembly(), ".Resources." + name);
        }
}
}

using FirstAssembly;
namespace SecondAssembly{
public static class B 

{
public static Stream FileNameFromType(string Name)

{
return = A.OpenResource(string name);
}
}
}

およびテストプロジェクトメソッド

using SecondAssembly;
namespace ThirdAssembly{
public class TestC
{

 [TestMethod()]
        public void StremSizTest()
        {
            // ARRANGE
            var Stream = B.FileNameFromType("ValidMetaData.xml");
            // ASSERT
            Assert.IsNotNull(Stream , "The Stream  object should not be null.");
        }
}
}
33
Saroop Trivedi

私はあなたがこのようにそれを行うことができるはずだと思います:

using System.Diagnostics;
using System.Linq;

...

StackFrame[] frames = new StackTrace().GetFrames();
string initialAssembly = (from f in frames 
                          select f.GetMethod().ReflectedType.AssemblyQualifiedName
                         ).Distinct().Last();

これにより、現在のスレッドで最初に開始された最初のメソッドを含むアセンブリが取得されます。したがって、メインスレッドにいない場合、これはEntryAssemblyとは異なる可能性があります。状況を正しく理解していれば、これは目的のアセンブリです。

次のような名前の代わりに実際のアセンブリを取得することもできます。

Assembly initialAssembly = (from f in frames 
                          select f.GetMethod().ReflectedType.Assembly
                         ).Distinct().Last();

編集-2015年9月23日現在

注意してください

GetMethod().ReflectedType

nullの可能性があるため、AssemblyQualifiedNameを取得すると例外がスローされる可能性があります。たとえば、ORM(linq2dbなど)POCOクラス専用のバニラc.torをチェックしたい場合、これは興味深いことです。

30
AVee

これにより、currentAssemblyを参照する初期アセンブリが返されます。

var currentAssembly = Assembly.GetExecutingAssembly();
var callerAssemblies = new StackTrace().GetFrames()
            .Select(x => x.GetMethod().ReflectedType.Assembly).Distinct()
            .Where(x => x.GetReferencedAssemblies().Any(y => y.FullName == currentAssembly.FullName));
var initialAssembly = callerAssemblies.Last();
11
realstrategos

Assembly.GetEntryAssembly()nunit-consoleからテストを実行した場合もnullになります。

実行中のアプリの名前だけが必要な場合は、次を使用します。

 System.Diagnostics.Process.GetCurrentProcess().ProcessName 

または

 Environment.GetCommandLineArgs()[0];

nunit-consoleの場合、「nunit-console」と「C:\ Program Files\NUnit 2.5.10\bin\net-2.0\nunit-console.exe」がそれぞれ表示されます。

6
tymtam

これを使用して私にとってはうまくいきました:

System.Reflection.Assembly.GetEntryAssembly().GetName()
5
Marcello

呼び出しの順序に関係なく、最上位のアセンブリを見つける必要がある場合は、

   Assembly.GetEntryAssembly()
4
Me.Name

特にユニットテストのコンテキストで実行する場合など、探しているものが完全にわかりません。

mscorlib.dll
Microsoft.VisualStudio.TestPlatform.Extensions.VSTestIntegration.dll

メソッドの呼び出しにつながる一連のアセンブリ内(またはテストランナーによっては似たようなもの)。

以下のコードは、呼び出しに含まれる各アセンブリの名前を出力します。

var trace = new StackTrace();
var assemblies = new List<Assembly>();
var frames = trace.GetFrames();

if(frames == null)
{
    throw new Exception("Couldn't get the stack trace");
}

foreach(var frame in frames)
{
    var method = frame.GetMethod();
    var declaringType = method.DeclaringType;

    if(declaringType == null)
    {
        continue;
    }

    var Assembly = declaringType.Assembly;
    var lastAssembly = assemblies.LastOrDefault();

    if(Assembly != lastAssembly)
    {
        assemblies.Add(Assembly);
    }
}

foreach(var Assembly in assemblies)
{
    Debug.WriteLine(Assembly.ManifestModule.Name);
}
0
mlorbetske

スタック内のフレーム数がわかっている場合は、StackFrameオブジェクトを使用して、前のフレームの数をスキップできます。

// You skip 2 frames
System.Diagnostics.StackFrame stack = new System.Diagnostics.StackFrame(2, false);
string assemblyName = stack.GetMethod().DeclaringType.AssemblyQualifiedName;

ただし、最初の呼び出しが必要な場合は、すべてのフレームを取得して最初の呼び出しを行う必要があります。 (AVeeソリューションを参照)

0
Hyralex

Assembly.GetEntryAssembly() はどうですか?プロセスのメインの実行可能ファイルを返します。

Process.GetCurrentProcess().MainModule.ModuleNameも、ManifestModule名( "yourapp.exe")とほぼ同じ値を返す必要があります。

0
Botz3000

試してください:

Assembly.GetEntryAssembly().ManifestModule.Name

これは、プロセスを開始するために実際に実行されたアセンブリである必要があります。

0
Jon Egerton