Сбой при возврате типа интерфейса - проблема с сериализацией? - PullRequest
0 голосов
/ 08 мая 2019

Моя система состоит из следующих частей:

  • Клиентский скрипт, который взаимодействует со службой через прокси
  • Служба, реализующая контракт на обслуживание
    Эта служба создаетсеанс с использованием / ссылкой на Session.dll и SessionContracts.dll (все скомпилированы из разных пространств имен)

Код службы выполняется, но Прокси-сервер прерывается по возвращении (System.ServiceModel.CommunicationObjectFaptedException).См. Код здесь ниже (возможно, что-то связанное с возвратом типа интерфейса?):

Обратите внимание, что в этом случае обрыв канала, но если я возвращаю ноль вместо сеанса, он больше не прерывается.

namespace SessionContracts  
{  
    public interface ISessionBase
    {
        void Connect();
    }
}

namespace SessionNameSpace  
{  
    [DataContract]  
    //    [KnownType(typeof(SessionBase))]     // Needed???
    [KnownType(typeof(ISessionBase))]  
    public class SessionBase : ISessionBase  
    {  
        public SessionBase() 
        {  
        }     
        public void Connect()  
        {  
        }  
    }  
}  

namespace Device.ServiceContract
{
    [ServiceContract(Namespace = "http://Device.Service", CallbackContract = typeof(IDeviceServiceCallback))]
    public interface IDeviceService
    {
        [OperationContract]
        ISessionBase CreateSession(Uin16 id);
    }
}

// This code works, but break within the Proxy on return
namespace Device.Service
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
                     ConcurrencyMode = ConcurrencyMode.Multiple)]

    public class DeviceService : IDeviceService
    {
        public DeviceService() { }

        ISessionBase CreateSession(Uin16 id) // Id not used for now
        {
            return new SessionBase();
        }
    }
}

// Proxy breaking on return
namespace Device.Proxy
{
    public class DeviceProxy : IDeviceService
    {
        public readonly IDeviceService _channel = null;

        private DeviceProxy()
        {
            // Channel factory stuffs here…
        }
    }

    private static DeviceProxy _instance = null;
    public static DeviceProxy Instance() => _instance ?? (_instance = new DeviceProxy());

    public ISessionBase CreateSession(UInt16 id)
    {
        ISessionBase a = _channel?.CreateSession(id);   // This line breaks
        return a;
    }
}    

Изменить, добавив сведения об исключении:

Сервер не предоставил значимого ответа;это может быть вызвано несоответствием контракта, преждевременным завершением сеанса или внутренней ошибкой сервера.

Server stack trace:  
   at System.ServiceModel.Channels.CommunicationObject.ThrowIfFaulted()  
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)  
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)  
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:   
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)  
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)  
   at Device.ServiceContract.IDeviceService.CreateSession()  
   at Device.Proxy.DeviceProxy.CreateSession() in E:\...\Device.Proxy\DeviceProxy.cs:line 71  
   at Client1.Program.Main(String[] args) in E:\...\Client1\Program.cs:line 97  

1 Ответ

1 голос
/ 10 мая 2019

Я полагал, что CreateSession в контракте на обслуживание должен знать больше о типе поддерживаемых сеансов (необходимо использовать ServiceKnownType).Если этого не сделать, служба не сможет узнать, как сериализовать данные этого типа.

Вот чего не хватало:

namespace Device.ServiceContract
{
    [ServiceContract(Namespace = "http://Device.Service", CallbackContract = typeof(IDeviceServiceCallback))]
    public interface IDeviceService
    {
        [OperationContract]
        [ServiceKnownType(typeof(SessionBase))]
        ISessionBase CreateSession(Uin16 id);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...