Может ли объект, возвращенный из другого домена приложения, быть сериализован в вызывающем домене?

В следующем коде, когдаSerializeToJson() метод вызван, я получаю следующее исключение на WriteObject():

Remoting не может найти поле "__identity" по типу "System.MarshalByRefObject"

Что я пытаюсь сделать возможным? Я немного незнаком с доменами приложений и связанными с ними вещами (прозрачный прокси и т. Д.). Я могу сериализовать свой TestClass в текущем домене приложения, но не понимаю, почему он здесь не работает. Спасибо за поиск.

using System;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace ConsoleApplication6
{
    public class BaseClass : MarshalByRefObject { }
    public class RemoteClass : BaseClass
    {
        public TestClass DoIt()
        {
            return new TestClass { Prop1 = DateTime.Now, Prop2 = 1234 };
        } 
    }

    [DataContract]
    public class TestClass : MarshalByRefObject
    {
        public TestClass() { }
        public TestClass(TestClass tc)
        {
            Prop1 = tc.Prop1;
            Prop2 = tc.Prop2;
        }
        [DataMember]
        public DateTime Prop1 { get; set; }
        [DataMember]
        public int Prop2 { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var appDomain = AppDomain.CreateDomain("myappdomain");
            var remoteClass = (RemoteClass)appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(RemoteClass).FullName);
            var returnedTestClass = remoteClass.DoIt();

            Console.WriteLine(SerializeToJson(returnedTestClass));
        }

        private static string SerializeToJson(object obj)
        {
            try
            {
                using (var stream = new MemoryStream())
                {
                    var serializer = new DataContractJsonSerializer(obj.GetType());
                    serializer.WriteObject(stream, obj);
                    stream.Position = 0;
                    using (var streamReader = new StreamReader(stream))
                    {
                        return streamReader.ReadToEnd();
                    }
                }
            }
            catch (Exception e)
            {
                // Error: Remoting cannot find field '__identity' on type 'System.MarshalByRefObject'.
                Console.WriteLine(e.Message);
                return string.Empty;
            }
        }
    }
}

2 ответа

Не надо смешивать [DataContract] с MarshalByRefObject для.NET Remoting. Просто используйте MarshalByRefObject как ты сделал с RemoteClass

Это может быть возможно с Protobuf:

https://github.com/mgravell/protobuf-net

Тем не менее, я хотел бы предупредить, что, основываясь на использовании [DataContract], он пахнет как WCF, который обычно является дорогой с односторонним движением. WCF печально известен тем, что диктует вам, как вы должны написать свое приложение - и это включает в себя сериализацию.

При этом у меня никогда не было проблем с JSON.Net для сериализации классов, помеченных [DataContract]. JsonConvert.Serialize() работает против System.Object.

Другие вопросы по тегам