简体   繁体   中英

Unable to cast object of type MyObject to type MyObject

I have this scenario where a webservice method I'm consuming in C# returns a Business object, when calling the webservice method with the following code I get the exception "Unable to cast object of type ContactInfo to type ContactInfo" in the reference.cs class of the web reference

Code:

ContactInfo contactInfo = new ContactInfo();
Contact contact = new Contact();

contactInfo = contact.Load(this.ContactID.Value);

Any help would be much appreciated.

This is because one of the ContactInfo objects is a web service proxy, and is in a different namespace.

It's a known problem with asmx-style web services. In the past I've implemented automatic shallow-copy to work around it ( here's how , although if I were doing it again I'd probably look at AutoMapper instead).

For example, if you have an assembly with the following class:

MyProject.ContactInfo

and you return an instance of it from a web method:

public class DoSomethingService : System.Web.Services.WebService
{
    public MyProject.ContactInfo GetContactInfo(int id)
    {
        // Code here...
    }
}

Then when you add the web reference to your client project, you actually get this:

MyClientProject.DoSomethingService.ContactInfo

This means that if, in your client application, you call the web service to get a ContactInfo , you have this situation:

namespace MyClientProject
{
    public class MyClientClass
    {
        public void AskWebServiceForContactInfo()
        {
            using (var service = new DoSomethingService())
            {
                MyClientProject.DoSomethingService.ContactInfo contactInfo = service.GetContactInfo(1);

                // ERROR: You can't cast this:
                MyProject.ContactInfo localContactInfo = contactInfo;
            }
        }
    }
}

It's on that last line that I use my ShallowCopy class:

namespace MyClientProject
{
    public class MyClientClass
    {
        public void AskWebServiceForContactInfo()
        {
            using (var service = new DoSomethingService())
            {
                MyClientProject.DoSomethingService.ContactInfo contactInfo = service.GetContactInfo(1);

                // We actually get a new object here, of the correct namespace
                MyProject.ContactInfo localContactInfo = ShallowCopy.Copy<MyClientProject.DoSomethingService.ContactInfo, MyProject.ContactInfo>(contactInfo);
            }
        }
    }
}

NOTE
This only works because the proxy class and the "real" class have exactly the same properties (one is generated from the other by Visual Studio).

As several of the other answers have suggested, it is because .NET sees them as two different classes. I personally would recommend using something like AutoMapper . I've been using it, and it seems pretty awesome. You can copy your objects in 1-2 lines of code.

Mapper.CreateMap<SourceClass, DestinationClass>();
destinationInstance = Mapper.Map<SourceClass, DestinationClass>(sourceInstance);

Actually this is not a bug. It's a problem with the version changes of your own project! Because your final run don't use the original imported references on compile!

For example, I was making a chat server, client. I used a packet structure to transmit data on client project. Then imported the same reference to server project.

When casting Packet packet = (Packet)binaryFormatter.Deserialize(stream); I got the same error. Because the actual running reference at server project is not the reference now at client project! Because I have rebuilt client project many times after!

In casting <new object>=(<new object>) <old object> always the new object needs to be a newer or same version as the old object!

So what I did was I built a separate project to create a DLL for the Packet class and imported the DLL file to both projects.

If I did any change to Packet class, I have to import the reference to both client and server again.

Then the casting won't give the above exception!

How are you referencing the class in your web service project as well as consumer project? If you have simply used a file link, this could well explain the cause of the error. The way serialiasation works for .NET (Web Services or otherwise I believe) is by using reflection to load/dump the data of an object. If the files are simply linked, then they are actually getting compiled to different types in different assemblies, which would explain why you have the same name but can't cast between them. I recommend creating a 'Core' library which both the web service and consumer project references, and contains the ContactInfo class which you use everywhere.

This isn't a problem - it's a feature.

They are two independent classes. Compare the two, and notice that the proxy class has none of the constructors, methods, indexers, or other behavior from the original class. This is exactly the same thing that would happen if you consumed the ASMX service with a Java program.

Seems like you have two different classes on both ends. Your application has ContactInfo class and your webservice also have the ContactInfo class. Both are two completely different classes. One way is to use the WebService class on your side. If you are using ContactInfo inside your web service then it will be serialized and will be available on the client side for use.

You can also modify your References.cs file generated by Visual Studio when the web reference is added. If you remove the proxy generated classes and add a reference (using statements) to your personal classes, you'll be able to use them straight away, without shallow copy / reflection or heavy mapping. (but you'll have to re-apply your modification if you regenerate the proxy layer).

I also tried to serialize the proxy object and deserialize them back in my DTO classes but it was quite heavy resources wise so I ended up modifying the References cs generated layer.

Hope it will help other people coming here :)

Kindly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM