ObjectHandle.Unwrap() und COM Add-in - Der transparente Proxy kann nicht umgewandelt werden

01/04/2010 - 12:36 von Stephan Janssen | Report spam
Hallo NG,

ich habe ein managed COM Add-in für Expression Web entwickelt, und möchte
nun dynamisch einen Typ aus einer .Net DLL instanzieren:

AppDomain tempDomain = AppDomain.CreateDomain("TempDomain");
ObjectHandle obj = Activator.CreateInstanceFrom(tempDomain, filename,
"Frontbox.Macros.Domain.Session");

Session session = (Session)obj.Unwrap();

filename verweist auf die DLL, Session ist ein Typ aus dieser DLL (erbt von
MarshalByRefObject). Die DLL ist als Referenz zum VS Project hinzugefügt
worden (und zwar genau die, die ich auch oben angegeben habe). Der
Konstruktor von Session wird auch aufgerufen, CreateInstanceFrom()
funktioniert also soweit.

Unwrap() wirft aber nun einen Fehler:

System.InvalidCastException: Der transparente Proxy kann nicht in den Typ
"Frontbox.Macros.Domain.Session" umgewandelt werden.

Eine Versuch mit einer Consolen-Anwendung und dynamisch eingebundener DLL
brachte kein Ergebnis: hier hat es genau so funktioniert.
Ich vermute mal, das Problem liegt daran, das ich das aus einem managed
COM-Add-in heraus machen möchte. Wenn dem so ist, bràuchte ich mal einen
Schubs in die richtige Richtung...

Ach ja,

Session session = new Session();

funktioniert natürlich, aber ich möchte das Objekt (bzw. die Assembly) auch
wieder entladen können, daher der Weg über AppDomain.

Stephan Janssen
www.frontbox.de
 

Lesen sie die antworten

#1 Stephan Janssen
01/04/2010 - 17:50 | Warnen spam
Ich beantworte meine Frage mal selber...

Unter http://www.west-wind.com/WebLog/posts/601200.aspx wird eine
Möglichkeit über einen Assembly-Resolver beschrieben.
Habe meine Code entsprechend umgebaut (s.u.), verstehe aber noch nicht ganz
wieso ein AssemblyResolver für die CurrentDomain hier funktioniert - ich
hàtte mal vermutet das man dieses für die tempDomain machen muß.

public void Test()
{
string filename =
@"P:\Current\...\bin\Release\Frontbox.Solaris.Macros.Domain.dll";

// Create application domain setup information.
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationName = "TempDomain";
domainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;

AppDomain tempDomain = AppDomain.CreateDomain("TempDomain", null,
domainSetup);

// need a custom resolver so we can load assembly from non current path
AppDomain.CurrentDomain.AssemblyResolve += new
ResolveEventHandler(CurrentDomain_AssemblyResolve);

try
{
Session session =
(Session)tempDomain.CreateInstanceFromAndUnwrap(filename,
"Frontbox.Macros.Domain.Session");

session.LoadAssemblies();
session.TestStart();
}
catch (Exception ex)
{
//...
}
finally
{
AppDomain.Unload(tempDomain);
}
}

/// <summary>
/// Custom assembly resolver to get assembly loaded from non current path.
/// </summary>
/// <returns>Loaded assembly or null.</returns>
/// <remarks>Code from http://www.west-wind.com/WebLog/posts/601200.aspx
</remarks>
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
Assembly assembly = System.Reflection.Assembly.Load(args.Name);
if (assembly != null)
return assembly;
}
catch
{ } // ignore load error

// *** Try to load by filename - split out the filename of the full
assembly name
// *** and append the base path of the original assembly (ie. look in the
same dir)
// *** NOTE: this doesn't account for special search paths but then that
never
// worked before either.
string[] parts = args.Name.Split(',');
string file =
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" +
parts[0].Trim() + ".dll";

return System.Reflection.Assembly.LoadFrom(file);
}

Stephan Janssen
www.frontbox.de

"Stephan Janssen" schrieb im Newsbeitrag
news:
Hallo NG,

ich habe ein managed COM Add-in für Expression Web entwickelt, und möchte
nun dynamisch einen Typ aus einer .Net DLL instanzieren:

AppDomain tempDomain = AppDomain.CreateDomain("TempDomain");
ObjectHandle obj = Activator.CreateInstanceFrom(tempDomain, filename,
"Frontbox.Macros.Domain.Session");

Session session = (Session)obj.Unwrap();

filename verweist auf die DLL, Session ist ein Typ aus dieser DLL (erbt
von
MarshalByRefObject). Die DLL ist als Referenz zum VS Project hinzugefügt
worden (und zwar genau die, die ich auch oben angegeben habe). Der
Konstruktor von Session wird auch aufgerufen, CreateInstanceFrom()
funktioniert also soweit.

Unwrap() wirft aber nun einen Fehler:

System.InvalidCastException: Der transparente Proxy kann nicht in den Typ
"Frontbox.Macros.Domain.Session" umgewandelt werden.

Eine Versuch mit einer Consolen-Anwendung und dynamisch eingebundener DLL
brachte kein Ergebnis: hier hat es genau so funktioniert.
Ich vermute mal, das Problem liegt daran, das ich das aus einem managed
COM-Add-in heraus machen möchte. Wenn dem so ist, bràuchte ich mal einen
Schubs in die richtige Richtung...

Ach ja,

Session session = new Session();

funktioniert natürlich, aber ich möchte das Objekt (bzw. die Assembly)
auch
wieder entladen können, daher der Weg über AppDomain.

Stephan Janssen
www.frontbox.de


Ähnliche fragen