Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[.NET Remoting] parser error: unknown assembly

Pagina: 1
Acties:

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
Mijn assembly-structuur is, in de simpelste vorm, als volgt:
server: server-programma, interfaces, plugin interfaces, plugin.
client: client-programma, interfaces, plugin interfaces.

Het probleem is zowat terug te leiden tot:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// interfaces assembly:
public interface IPluginBase { /* */ }
public interface ISomePluginContainer
{
  IPluginBase GetPlugin();
}


// plugin interfaces assembly:
public interface ISomeObject { /* */ }
public interface ISpecificPlugin
{
  ISomeObject GetSomeObject();
}

// plugin assembly
public class SomeObject : MarshalByRefObject, ISomeObject { /* */ }
public class SpecificPlugin : MarshalByRefObject, IPluginBase, ISpecificPlugin
{
  public ISomeObject GetSomeObject() { return new SomeObject(); }
}

// programma assembly
class SomePluginContainer : MarshalByRefObject, ISomePluginContainer
{
  // plugins worden dynamisch geladen met reflection.
  IPluginBase GetPlugin() { }
}

static int main()
{
  // set up remoting
  //
  SomePluginContainer ctr = new SomePluginContainer();
  ObjRef ref = RemotingServices.Marshal(ctr);
}

Aan de client kant:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
// refereert zowel interfaces als plugin interfaces assembly
static int main
{
  // setup remoting
  ISomePluginContainer ctr = (ISomePluginContainer)Activator.GetObject(...);
  IPluginBase plugin = ctr.GetPlugin();
  if (plugin is ISpecificPlugin)
  {
    ISpecificPlugin specPlugin = plugin as ISpecificPlugin;
    ISomeObject obj = specPlugin.GetSomeObject(); // hier krijg ik de fout.
  }
}


De exception die ik krijg is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
System.Runtime.Serialization.SerializationException: Parserfout. Er is geen assembly gekoppeld aan XML-sleutel a2:http://schemas.microsoft.com/clr/nsassem/XXX.Plugins/XXX.Plugins%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3D22271cae2e665f51 SomeObject

Server stack trace: 
   bij System.Runtime.Serialization.Formatters.Soap.SoapHandler.ProcessGetType(String value, String xmlKey, String& assemblyString)
   bij System.Runtime.Serialization.Formatters.Soap.SoapHandler.ProcessArray(ParseRecord pr, Int32 firstIndex, Boolean IsInterop)
   bij System.Runtime.Serialization.Formatters.Soap.SoapHandler.ProcessType(ParseRecord pr, ParseRecord objectPr)
   bij System.Runtime.Serialization.Formatters.Soap.SoapHandler.ProcessAttributes(ParseRecord pr, ParseRecord objectPr)
   bij System.Runtime.Serialization.Formatters.Soap.SoapHandler.StartChildren()
   bij System.Runtime.Serialization.Formatters.Soap.SoapParser.ParseXml()
   bij System.Runtime.Serialization.Formatters.Soap.SoapParser.Run()
   bij System.Runtime.Serialization.Formatters.Soap.ObjectReader.Deserialize(HeaderHandler handler, ISerParser serParser)
   bij System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Deserialize(Stream serializationStream, HeaderHandler handler)
   bij System.Runtime.Remoting.Channels.CoreChannel.DeserializeSoapResponseMessage(Stream inputStream, IMessage requestMsg, Header[] h, Boolean bStrictBinding)
   bij System.Runtime.Remoting.Channels.SoapClientFormatterSink.DeserializeMessage(IMethodCallMessage mcm, ITransportHeaders headers, Stream stream)
   bij System.Runtime.Remoting.Channels.SoapClientFormatterSink.SyncProcessMessage(IMessage msg)

Exception rethrown at [0]: 
   bij System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   bij System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   bij XXX.Interfaces.Plugins.ISpecificPlugin.GetSomeObject()


Google vertelt me dat dit niet zo vaak voorkomt, maar een goeie hint was om de Plugins assembly naast het client programma te zetten. Dit werkt, maar is natuurlijk niet netjes. De clients hebben helemaal niets te maken met de implementatie van mijn interfaces.

Remoting doet alsof ik het object wil hebben, terwijl ik enkel geinteresseerd ben in de interface natuurlijk. Het rare van de zaak is dat de plugin zelf wel werkt, terwijl het sub-object die in diezelfde assembly zit, niet werkt.

Tweede onbegrijpbare is dat de exceptie tijdens het _deserializen_ aan de _server_ kant opgeworpen wordt, terwijl ik toch echt de fout zou verwachten tijdens het deserializen aan de client kant.

ASSUME makes an ASS out of U and ME


  • whoami
  • Registratie: December 2000
  • Laatst online: 22:01
Hmm...
Is SomeObject ook een MarshalByRef object ? (Een object dat nl. door een remote object gecreeërd wordt, is ook remoted (client activated)).

(Ik zou trouwens dat Dutch Language Pack deinstalleren, dan krijg je foutmeldingen waarbij je meer hits krijgt op google ;) )

[ Voor 30% gewijzigd door whoami op 27-02-2008 20:59 ]

https://fgheysels.github.io/


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
Ik kan meestal wel redelijk goed vertalen... Ik heb bijvoorbeeld gegoogled op: "parser error, no assembly associated with key" wat de engelstalige vertaling is voor die fout.

SomeObject is inderdaad MarshalByRefObject. Het wordt echter op de server genew'd en opgeslaan in een lijst. Daar kom ik echter nog niet aangezien de eigenlijke call een (initieel lege) array van ISomeObject's retourneert, waar het dus al fout loopt.

Ik heb bovendien een wrapper rond de marshalbyrefobject, om een oneindige lifetime te hebben, aangezien de server-app bepaalt welke lifetime objecten hebben.

ASSUME makes an ASS out of U and ME


  • whoami
  • Registratie: December 2000
  • Laatst online: 22:01
H!GHGuY schreef op woensdag 27 februari 2008 @ 21:08:

Ik heb bovendien een wrapper rond de marshalbyrefobject, om een oneindige lifetime te hebben, aangezien de server-app bepaalt welke lifetime objecten hebben.
Hoe bedoel je dat ?

https://fgheysels.github.io/


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
Mijn objecten zijn niet zomaar business objects of iets dergelijk, die een beperkte lifetime hebben.
Het zijn actieve objecten die gewoon geconfigureerd worden over remoting.

Ik heb misschien niet genoeg gelezen over remoting lifetimes, maar uit eerdere ervaringen met lifetime issues, heb ik dit maar als voorzorg genomen.

Dit geheel terzijde aangezien dit niets met het probleem te maken heeft...

Ik heb nog enkele andere dingen geprobeerd, evenwel (zoals verwacht) zonder success:
Members van de SomeObject class die eveneens classes waren binnen diezelfde assembly omzetten naar hun respectieve interface.
Default constructor toevoegen.

Ik begin hopeloos te worden. Google laat ook al niet veel weten...


ONTOPIC:
Ik heb net nog even iets geprobeerd, met success.

De ISomeObject GetObject() is eigenlijk een ISomeObject[] GetObject() call.
Ik heb er nu toch even ISomeObject GetObject(), dus 1 enkel object, van gemaakt en dan werkt het wel. Het probleem ligt dus puur aan de array.

Bovendien wordt in de GetObjects() call volgend equivalent uitgevoerd:
C#:
1
2
3
4
ISomeObject[] GetObjects()
{
  return new List<SomeObject>( /* opvullen */ ).ToArray() as ISomeObject[];
}


Dit lost natuurlijk nog mijn probleem niet op, maar het is alvast een stap in de goeie richting om te weten dat het probleem te wijten is aan de array...

[ Voor 31% gewijzigd door H!GHGuY op 28-02-2008 19:49 ]

ASSUME makes an ASS out of U and ME


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
De reden is me nu denk ik al duidelijk.
Array is een value-type en dus wil hij de objecten serializen. Daarvoor heeft de andere kant natuurlijk die assembly nodig.

Weet iemand een manier om verzamelingen objecten byref over remoting boundaries terug te geven?

List<ISomeObject> kan niet, jammer genoeg

[ Voor 7% gewijzigd door H!GHGuY op 01-03-2008 07:50 ]

ASSUME makes an ASS out of U and ME


  • whoami
  • Registratie: December 2000
  • Laatst online: 22:01
Mja, objecten die je doorstuurt moeten idd serializable zijn, en moeten dus zowel aan client & server kant gekend zijn.
Als het object dat je doorstuurt serializable is, en gekend is aan de client & aan de server kant, dan kan je ook gewoon een array doorsturen die objecten van dat type bevat.

In mijn project waar ik remoting gebruik, heb ik gewoon een aparte assembly met daarin mijn DTO's, en die assembly staat zowel op de client, als op de server.
(Verder heb ik op de client enkel interfaces die beschrijven welke functionaliteit er remote beschikbaar is)

https://fgheysels.github.io/


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
Ik heb het nu kunnen oplossen door een ArrayList door te zenden.
Een betere oplossing, waarin het type van m'n object vast ligt is overigens nog altijd welkom.

ASSUME makes an ASS out of U and ME


  • Rhapsody
  • Registratie: Oktober 2002
  • Laatst online: 23:24

Rhapsody

In Metal We Trust

Gebruik je Client Activated Objects of Server Activated Objects (SingleCall, Singleton)?

het probleem met CAO is namelijk dat je het hele object aan de client-kant moet hebben. Een interface kun je daar niet voor gebruiken.

[ Voor 46% gewijzigd door Rhapsody op 01-03-2008 17:56 ]

🇪🇺 pro Europa! | Puinhoop Veroorzaken en Vertrekken (PVV)


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
Ik gebruik eigenlijk geen van beide.

Ik doe zoiets als:
C#:
1
2
3
4
5
6
7
8
9
10
// Aanmaak van remoting sinks voor formatting, encryptie, authenticatie
// Aanmaak van channel
System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(channel, false);
MyObject obj = new MyObject()
obj.Prepare()
System.Runtime.Remoting.ObjRef ref = System.Runtime.Remoting.RemotingServices.Marshal(obj, "MyObject");
// wacht op bepaalde events
System.Runtime.Remoting.RemotingServices.Disconnect(obj);
System.Runtime.Remoting.Channels.ChannelServices.UnregisterChannel(channel);
obj.Cleanup();

(tenzij je dit rekent onder SAO of CAO)
Aan de client kant heb ik een assembly die het omgekeerde doet, sinks aanmaken en remote object aanvragen, retourneren als IMyObject interface.

De hierarchische structuur die vertrekt vanaf MyObject moet in leven gehouden worden voor de hele duur van de applicatie. Remoting dient enkel om configuratie te doen van de app.

[ Voor 8% gewijzigd door H!GHGuY op 02-03-2008 10:46 ]

ASSUME makes an ASS out of U and ME

Pagina: 1