是否可以从.net webservices返回接口,或者只返回具体类?

时间:2022-03-15 20:11:00

I need to return a complex type from a webservice and had constructed the class MyComplexType which implements the interface IMyComplexType. Now in my webservice I have a method that should return an object that implements IMyComplexType like so:

我需要从webservice返回一个复杂类型,并构造了MyComplexType类,它实现了接口IMyComplexType。现在在我的webservice中,我有一个方法应该返回一个实现IMyComplexType的对象,如下所示:

[WebMethod]
public IMyComplexType GetMyComplexType()
{
   IMyComplexType myCt = new MyComplexType();
   ...
   return myCt; 
}

Everything compiles ok but when I run the webservice it throws an exception as follows:

一切都编译好,但是当我运行webservice时,它会抛出一个异常,如下所示:

System.NotSupportedException: Cannot serialize interface MyWebService.IMyComplexType.

Is this by design or am I missing something. Can I decorate my class or interface somehow to allow this? Do I have to eliminate all interfaces and only work with concrete and perhaps abstract base-classes to be able to do this with .net webservices?

这是设计还是我遗漏了一些东西。我可以以某种方式装饰我的类或界面以允许这个吗?我是否必须消除所有接口,并且只能使用具体的,也许是抽象的基类,以便能够使用.net webservices执行此操作?

Edit:

this is the interface I am trying to serialize:

这是我尝试序列化的接口:

public interface ICustomer
{
     long Id {get; set;}
     string Name {get; set;}
     string EmailAddress {get; set;}
}

3 个解决方案

#1


Short answer is no, you can't return an interface through a WebService.

简短的回答是不,你不能通过WebService返回一个接口。

Long answer is that you can kind of get the behaviour you want, but it's a bit hacky. The solution is to use binary serialization. So you serialize your type to bytes, have the web method return a series of bytes and then on the other side you would deserialize the bytes back to your complex type.

答案很长,你可以得到你想要的行为,但它有点hacky。解决方案是使用二进制序列化。因此,您将类型序列化为字节,让Web方法返回一系列字节,然后在另一侧将字节反序列化为复杂类型。

For example

[WebMethod]
public byte[] GetMyComplexType()
{

   IMyComplexType myCt = new MyComplexType();
   ...

   MemoryStream stream = new MemoryStream();
   IFormatter fmt = new BinaryFormatter();
   fmt.Serialize(stream, myCt);
   stream.Flush();
   byte[] bytes = stream.ToArray();
   stream.Close();

   return bytes;
}

You'll need to convert everything back at the other end.

你需要在另一端转换所有东西。

byte[] bytes = service.GetMyComplexType();
MemoryStream stream = new MemoryStream(bytes);
BinaryFormatter fmt = new BinaryFomatter();
MyComplexType myCt = fmt.DeSerialize(stream);

You can probably clean the deserialization up by creating a generic method. I should add, that you'll need to make sure you can reference the complex type on the client.

您可以通过创建泛型方法来清除反序列化。我应该补充一点,你需要确保你可以在客户端上引用复杂类型。

Alternatively, if they are your interfaces then you could turn them into Abstract Classes. However, this won't work if you want the class to implement multiple interfaces (or you already inherit from another class) as you can only inherit one class. If you need some polymorphic behaviour on the client, you'll need to use the XmlInclude attribute.

或者,如果它们是您的接口,那么您可以将它们转换为抽象类。但是,如果您希望类实现多个接口(或者您已从其他类继承),则无法继承,因为您只能继承一个类。如果在客户端上需要某些多态行为,则需要使用XmlInclude属性。

#2


It's been a while, but I believe you need only make your interfaces extend ISerializable and all should be good.

已经有一段时间了,但我相信你只需要让你的接口扩展到ISerializable,一切都应该是好的。

#3


You don't need to implement ISerializable - simply marking the interface with the Serializable attribute should be all you need to do. If you want to implement the interface, by all means go ahead - it will give you fine-grained control over how the interface is serialized. But I would imagine that the default implementation should be ok. Also check to make sure that all the interface members are serializable as well.

您不需要实现ISerializable - 只需使用Serializable属性标记接口应该只需要做。如果要实现接口,请务必继续 - 它将为您提供对接口序列化方式的细粒度控制。但我认为默认实现应该没问题。还要检查以确保所有接口成员都是可序列化的。

[Edit] I wasn't even thinking straight - there is no way that you will be able to implement ISerializable as you are trying to serialize an iterface anyway. The place where ISerializable would be appropriate would be on custom types that need custom serialization that are exposed by the interface.

[编辑]我甚至没有直接思考 - 无论如何你都无法实现ISerializable,因为你正试图序列化iterface。 ISerializable适合的位置将是需要由接口公开的自定义序列化的自定义类型。

#1


Short answer is no, you can't return an interface through a WebService.

简短的回答是不,你不能通过WebService返回一个接口。

Long answer is that you can kind of get the behaviour you want, but it's a bit hacky. The solution is to use binary serialization. So you serialize your type to bytes, have the web method return a series of bytes and then on the other side you would deserialize the bytes back to your complex type.

答案很长,你可以得到你想要的行为,但它有点hacky。解决方案是使用二进制序列化。因此,您将类型序列化为字节,让Web方法返回一系列字节,然后在另一侧将字节反序列化为复杂类型。

For example

[WebMethod]
public byte[] GetMyComplexType()
{

   IMyComplexType myCt = new MyComplexType();
   ...

   MemoryStream stream = new MemoryStream();
   IFormatter fmt = new BinaryFormatter();
   fmt.Serialize(stream, myCt);
   stream.Flush();
   byte[] bytes = stream.ToArray();
   stream.Close();

   return bytes;
}

You'll need to convert everything back at the other end.

你需要在另一端转换所有东西。

byte[] bytes = service.GetMyComplexType();
MemoryStream stream = new MemoryStream(bytes);
BinaryFormatter fmt = new BinaryFomatter();
MyComplexType myCt = fmt.DeSerialize(stream);

You can probably clean the deserialization up by creating a generic method. I should add, that you'll need to make sure you can reference the complex type on the client.

您可以通过创建泛型方法来清除反序列化。我应该补充一点,你需要确保你可以在客户端上引用复杂类型。

Alternatively, if they are your interfaces then you could turn them into Abstract Classes. However, this won't work if you want the class to implement multiple interfaces (or you already inherit from another class) as you can only inherit one class. If you need some polymorphic behaviour on the client, you'll need to use the XmlInclude attribute.

或者,如果它们是您的接口,那么您可以将它们转换为抽象类。但是,如果您希望类实现多个接口(或者您已从其他类继承),则无法继承,因为您只能继承一个类。如果在客户端上需要某些多态行为,则需要使用XmlInclude属性。

#2


It's been a while, but I believe you need only make your interfaces extend ISerializable and all should be good.

已经有一段时间了,但我相信你只需要让你的接口扩展到ISerializable,一切都应该是好的。

#3


You don't need to implement ISerializable - simply marking the interface with the Serializable attribute should be all you need to do. If you want to implement the interface, by all means go ahead - it will give you fine-grained control over how the interface is serialized. But I would imagine that the default implementation should be ok. Also check to make sure that all the interface members are serializable as well.

您不需要实现ISerializable - 只需使用Serializable属性标记接口应该只需要做。如果要实现接口,请务必继续 - 它将为您提供对接口序列化方式的细粒度控制。但我认为默认实现应该没问题。还要检查以确保所有接口成员都是可序列化的。

[Edit] I wasn't even thinking straight - there is no way that you will be able to implement ISerializable as you are trying to serialize an iterface anyway. The place where ISerializable would be appropriate would be on custom types that need custom serialization that are exposed by the interface.

[编辑]我甚至没有直接思考 - 无论如何你都无法实现ISerializable,因为你正试图序列化iterface。 ISerializable适合的位置将是需要由接口公开的自定义序列化的自定义类型。