Frage

Ich habe versucht, den folgenden Code zur Arbeit zu kommen (alles in der gleichen Baugruppe definiert):

namespace SomeApp{

public class A : MarshalByRefObject
{
   public byte[] GetSomeData() { // }
}

public class B : MarshalByRefObject
{
   private A remoteObj;

   public void SetA(A remoteObj)
   {
      this.remoteObj = remoteObj;
   }
}

public class C
{
   A someA = new A();
   public void Init()
   {
       AppDomain domain = AppDomain.CreateDomain("ChildDomain");
       string currentAssemblyPath = Assembly.GetExecutingAssembly().Location;
       B remoteB = domain.domain.CreateInstanceFromAndUnwrap(currentAssemblyPath,"SomeApp.B") as B;
       remoteB.SetA(someA); // this throws an ArgumentException "Object type cannot be converted to target type."
   }
}

}

Was ich versuche zu tun, einen Verweis von einer Instanz in der ersten AppDomain der untergeordneten Domäne erstellt ‚A‘ übergeben und haben das Kind Domäne eine Methode auf der ersten Domäne auszuführen. In einem gewissen Punkt auf Code ‚B‘ Ich werde Anruf ‚remoteObj.GetSomeData ()‘. Dies muss getan werden, da die ‚byte []‘ von ‚GetSomeData‘ Methode muss auf dem ersten Appdomain 'berechnet werden. Was soll ich tun, um die Ausnahme zu vermeiden, oder was kann ich tun, um das gleiche Ergebnis zu erreichen?

War es hilfreich?

Lösung

kann ich das Problem duplizieren, und es scheint TestDriven.net und / oder xUnit.net zusammenzuhängen. Wenn ich C.Init () als ein Testverfahren laufen, bekomme ich die gleiche Fehlermeldung. Allerdings, wenn ich C.Init () von einer Konsole-Anwendung ausführen, ich habe nicht die Ausnahme erhalten.

Sind Sie die gleiche Sache zu sehen, laufen C.Init () von einem Gerät zu testen?

Edit: Ich bin auch in der Lage, das Problem mit NUnit zu duplizieren und TestDriven.net. Ich bin auch in der Lage der Fehler mit dem NUnit Läufer statt TestDriven.net zu duplizieren. So scheint das Problem zu laufen diesen Code durch einen Test-Framework verwandt zu sein, obwohl ich bin mir nicht sicher, warum.

Andere Tipps

Die eigentliche Ursache wurde Ihre dll wurde von verschiedenen Standorten in den beiden unterschiedlichen Anwendungsdomänen geladen zu werden. Diese Ursachen .NET denken, dass sie unterschiedliche Baugruppen sind die natürlich Mittel die Typen unterschiedlich sind (auch wenn sie die gleiche Klasse Namen, Namensraum usw.).

Der Grund Jeffs Test nicht bestanden, wenn durch einen Einheit Test-Framework laufen, weil Unit-Test-Frameworks im Allgemeinen AppDomains mit Shadow auf „true“ erstellen. Aber Ihre manuell erstellt AppDomain würde Shadow default = „false“. Dies würde bewirken, dass die DLLs von verschiedenen Orten aus, die führt zu dem schönen geladen werden „Objekttyp Zieltyp nicht konvertiert werden kann.“ Fehler.

UPDATE: Nach weiteren Tests, scheint es auf die Application zu kommen unterschiedlich zwischen den beiden AppDomains. Wenn sie übereinstimmen, dann die oben beschriebene Szenario funktioniert. Wenn sie unterschiedlich sind es nicht (obwohl ich bestätigt habe, dass die dll in beiden AppDomains aus dem gleichen Verzeichnis geladen werden mit windbg) Auch, wenn ich auf Shadow drehen = „true“ in beide meine AppDomains, dann scheitert es mit einer anderen Nachricht:. "System.InvalidCastException: Objekt implementieren muss IConvertible"

UPDATE2: Literatur führt mich zu glauben, es Contexts an laden verwandt ist. Wenn Sie eine der „Von“ Methoden (Assembly.LoadFrom oder appDomain.CreateInstanceFromAndUnwrap), wenn sich die Anordnung in einer der normalen Lastpfade gefunden wird (der Application oder einer der Antastwege), dann ist geladen in die Standard Last-Kontext. Wenn die Montag dort nicht gefunden wird, dann wird es in die Last aus dem Kontext geladen. Also, wenn beide AppDomains perfekt miteinander harmonieren Application ist, dann, obwohl wir ein „Aus“ Methode verwenden, sie sind beide geladen in ihren jeweiligen AppDomain der Standard-Load-Kontext. Aber wenn die Application der verschieden sind, dann ein AppDomain wird die in seinem Standard-Load-Kontext hat Baugruppe, während die andere die Montag in seiner Last Von Kontext hat.

Dies ist ein Kommentar zu @RussellMcClure aber wie es zu komplex für einen Kommentar ist poste ich dies als eine Antwort:

Ich bin innerhalb einer ASP.NET-Anwendung und das Ausschalten Schatten-Kopie (das auch das Problem lösen würde) ist nicht wirklich eine Option, aber ich fand die folgende Lösung:

AppDomainSetup adSetup = new AppDomainSetup();
if (AppDomain.CurrentDomain.SetupInformation.ShadowCopyFiles == "true")
{
    var shadowCopyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    if (shadowCopyDir.Contains("assembly"))
        shadowCopyDir = shadowCopyDir.Substring(0, shadowCopyDir.LastIndexOf("assembly"));

    var privatePaths = new List<string>();
    foreach (var dll in Directory.GetFiles(AppDomain.CurrentDomain.SetupInformation.PrivateBinPath, "*.dll"))
    {
        var shadowPath = Directory.GetFiles(shadowCopyDir, Path.GetFileName(dll), SearchOption.AllDirectories).FirstOrDefault();
        if (!String.IsNullOrWhiteSpace(shadowPath))
            privatePaths.Add(Path.GetDirectoryName(shadowPath));
    }

    adSetup.ApplicationBase = shadowCopyDir;
    adSetup.PrivateBinPath = String.Join(";", privatePaths);
}
else
{
    adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
    adSetup.PrivateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
}

Damit wird das Schatten-Kopie-Verzeichnis der wichtigsten app-Domäne als Anwendungsbasis verwenden und alle Schatten kopiert Baugruppen an den privaten Pfad hinzufügen, wenn Schattenkopie aktiviert ist.

Wenn jemand einen besseren Weg, hat dies zu tun, erklären Sie mir bitte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top