Ice.UnexpectedObjectException from library, ConsoleApp runs same library with no error

mfuribondomfuribondo Member Michael FuribondoOrganization: MCProject: ExcelDNA calling multiple ICE servers

I am getting the following ICE exception when trying to run a library which uses ICE to communicate with multiple ICE servers. I am packaging this library into an Excel plug in using ExcelDNA. The strange thing is that when call the library from a console application, I do not get the exception. The exception is only thrown when i run the excel plugin.

  • The servers and the client use the same .ice files and Ice.dll. They were also sliced with the same version of slice2cs.exe.
  • All of the servers are communicating successfully with the client except one - ReferenceDataLite
  • The error i pasted below is for one object - zcClassification, however all of objects from ReferenceDataLite throw the same error
  • The servers are running as x64 but the library is built as x86 because it needs to run in Excel 32bit. (Having said this, I did build the library as x64 and ran it in Excel x64 and got the same error) ALSO, my console app runs fine whether I run it as x64 or x86.

  • I have been trying to get this working for 8 days, any help would be greatly appreciated!

Here is the error:
Ice.UnexpectedObjectException
reason = "expected element of type ::Mag::ReferenceDataLite::ZeroC::zcClassification' but received ::Mag::ReferenceDataLite::ZeroC::zcClassification"
type = "::Mag::ReferenceDataLite::ZeroC::zcClassification"
expectedType = "::Mag::ReferenceDataLite::ZeroC::zcClassification"
at IceInternal.Ex.throwUOE(String expectedType, String actualType)
at IceInternal.ArrayPatcher 1.patch(Object v)
at IceInternal.BasicStream.EncapsDecoder.unmarshal(Int32 index, Object v)
at IceInternal.BasicStream.EncapsDecoder10.readInstance()
at IceInternal.BasicStream.EncapsDecoder10.readPendingObjects()
at IceInternal.BasicStream.readPendingObjects()

The exception is being thrown on the client on the readPendingObjects() row of generated code:
public Mag.ReferenceDataLite.ZeroC.zcClassification[] end_getClassifications(Ice.AsyncResult r__)
{
IceInternal.OutgoingAsync outAsync__ = IceInternal.OutgoingAsync.check(r__, this, getClassifications_name);
try
{
if(!outAsync
.wait())
{
try
{
outAsync__.throwUserException();
}
catch(Ice.UserException ex__)
{
throw new Ice.UnknownUserException(ex__.ice_name(), ex__);
}
}
Mag.ReferenceDataLite.ZeroC.zcClassification[] ret__;
IceInternal.BasicStream is__ = outAsync__.startReadParams();
ret__ = Mag.ReferenceDataLite.ZeroC.zcClassificationsHelper.read(is__);
is__.readPendingObjects();//EXCEPTION IS THROW HERE
outAsync__.endReadParams();
return ret__;
}
finally
{
outAsync__.cacheMessageBuffers();
}
}

Best Answer

  • xdmxdm ZeroC Staff La Coruña, SpainJose Gutierrez de la ConchaOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff
    Accepted Answer

    Hi,

    Ice load assemblies dynamically to be able to instantiate classes, this is the reason you don't see any issues with operations that doesn't return classes.

    I think one possible solution here is to install an object factory so that Ice doesn't need to resort to dynamic loaded assemblies to instantiate classes.

    private class MyObjectFactory : Ice.ObjectFactory {
        public Ice.Object create(string type) {
            if (type.Equals("::Mag::ReferenceDataLite::ZeroC::zcClassification")) {
                return new Mag.ReferenceDataLite.ZeroC.zcClassification();
            }
        }
    }
    
    Ice.ObjectFactory factory = new MyObjectFactory();
    communicator.addObjectFactory(factory, "::Mag::ReferenceDataLite::ZeroC::zcClassification");
    

Answers

  • xdmxdm ZeroC Staff La Coruña, SpainAdministrators, ZeroC Staff Jose Gutierrez de la ConchaOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    Can you give us a bit more info of what you are doing. Are you loading multiple plugins that use the Ice.dll?

  • mfuribondomfuribondo Member Michael FuribondoOrganization: MCProject: ExcelDNA calling multiple ICE servers

    No, just one plugin. When i instantiate the addin from a consoleapplication, i do not get the exception. however when i open excel with the plug in, i do get the exception.

    Here is my program.cs from my consoleapp.
    class Program
    {
    static void Main(string[] args)
    {
    TradingAddIn.TradingAddIn.AddInRoot a = new TradingAddIn.TradingAddIn.AddInRoot();
    a.AutoOpen();
    }
    }

    and here is tradingaddin.cs
    public class AddInRoot : IExcelAddIn
    {
    public void AutoOpen()
    {
    try
    {
    TradingAddIn.initialize();
    }
    catch (Exception e)
    {
    System.Windows.Forms.MessageBox.Show(e.ToString(), "Error loading TradingAddIn2");
    }
    }
    }

    So, the console app uses all of the code from the TradingAddin.dll. I can make other ice calls to other ice servers when the exceladdin loads, just not to the referencedatalite server. the problem seems specific to my referencedatalite server/client.

  • xdmxdm ZeroC Staff La Coruña, SpainAdministrators, ZeroC Staff Jose Gutierrez de la ConchaOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff
    reason = "expected element of type ::Mag::ReferenceDataLite::ZeroC::zcClassification' but received ::Mag::ReferenceDataLite::ZeroC::zcClassification"
    

    The type names being equals indicate that you have several versions of this type loaded, and .NET consider they are not the same type.

    That could happen if TradingAddin.dll. is somehow loaded multiple times. and the zcClassification objects come from different instances of the assembly.

    Looking at ExceIDna I think that the version of the library loaded by them is not visible to Ice and the Ice Assembly helper loads it again, I see there is a LoadFromBytes="true" property that could be related.

  • mfuribondomfuribondo Member Michael FuribondoOrganization: MCProject: ExcelDNA calling multiple ICE servers

    I appreciate your time and response.
    Unfortunately changing it to LoadFromBytes in the .dna file didnt resolve the issue. same error being thrown.

    I have no idea how two instances of TradingAddin.dll are being loaded...

    I just realized that the zcClassification object is generated in a different project. That project is referenced by the TradingAddIn project along with two other projects. There are about 40 different projects that TradingAddIn reference. Is there a way for me to verify which dll is being loaded multiple times?

  • mfuribondomfuribondo Member Michael FuribondoOrganization: MCProject: ExcelDNA calling multiple ICE servers

    also, i'm not sure if this will help, but I did a wireshark capture on both teh console application and when i open the excelplugin. The bytes that come back from the RefDataLiteServer are exactly the same in both cases.

  • xdmxdm ZeroC Staff La Coruña, SpainAdministrators, ZeroC Staff Jose Gutierrez de la ConchaOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff
    Accepted Answer

    Hi,

    Ice load assemblies dynamically to be able to instantiate classes, this is the reason you don't see any issues with operations that doesn't return classes.

    I think one possible solution here is to install an object factory so that Ice doesn't need to resort to dynamic loaded assemblies to instantiate classes.

    private class MyObjectFactory : Ice.ObjectFactory {
        public Ice.Object create(string type) {
            if (type.Equals("::Mag::ReferenceDataLite::ZeroC::zcClassification")) {
                return new Mag.ReferenceDataLite.ZeroC.zcClassification();
            }
        }
    }
    
    Ice.ObjectFactory factory = new MyObjectFactory();
    communicator.addObjectFactory(factory, "::Mag::ReferenceDataLite::ZeroC::zcClassification");
    
  • mfuribondomfuribondo Member Michael FuribondoOrganization: MCProject: ExcelDNA calling multiple ICE servers

    Thank you very much! that worked!

Sign In or Register to comment.