Aishwarya Hegde Ответов: 1

Сериализация Wcf с использованием интерфейса iserializable


Это должно быть возможно, однако я тщательно искал и не нашел ответов на этот вопрос, используя концепцию интерфейса WCF ISerializable. Надеюсь, эксперты смогут помочь.

Любая документация, которую я прочитал, относится только к концепции info.AddValue (...), аналогичной тем, что есть в https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.iserializable?view=netframework-4.8

Таким образом, у меня есть SW, который выполняет такие операции, как обработка изображений в одном EXE-файле. Я хотел бы использовать подход WCF Service/Client и выполнять эту обработку на отдельных сервисах на одном ПК или разных ПК. Ну в основном распределите процесс.

У меня есть служба WCF с конечными точками, подключается и связывается со службами и т. д., Все здесь хорошо.

Я хочу отправить весь объект класса(с его локальными переменными/объектами), который был создан на клиенте, в службу.

У меня есть класс, производный от интерфейса ISerializable. Атрибут класса-это [сериализуемый]. Она имеет требуется конструктор &амп; метод GetObjectData() публичных Фу(информация SerializationInfo, StreamingContext контекстные) общественного недействительными метод GetObjectData(SerializationInfo информация, StreamingContext контекстные)

Этот объект сериализуется с помощью BinaryFormatter в байт[] и отправляется. На стороне службы он десериализуется в объект класса.

Во время сериализации он действительно входит в GetObjectData() и выполняет свою задачу. Но во время десериализации объект класса, который я получаю, является просто объектом по умолчанию, а не объектом, который был отправлен, локальные переменные/объекты не инициализируются.

Этот объект класса не является синглтоном, и я не хочу этого делать, так как существует много экземпляров этого класса в отдельных потоках. Я бы подумал, что не нужно делать Addvalue для каждого параметра класса. Поскольку это всего лишь один класс, на который я ссылаюсь, в конечном итоге мне придется отправить много таких объектов класса.

Я пробовал использовать вспомогательный класс с концепцией интерфейса IObjectReference, используя GetRealObject() --> Но как я могу получить исходный объект из этого?

Я читал о суррогатах, опять же нет хорошего примера о том, как отправить весь объект класса.

Я хочу, чтобы весь объект этого класса был на стороне обслуживания.

Классы, которые я хочу отправить, намного больше и сложнее, чем 2 Int, в нем есть объекты других классов, словари и т. д. Дело в том, как получить объект этого класса, кажется, что он находится в объекте SerializationInfo, но не может найти способ его получить

Надеюсь, я ясно сформулировал свой вопрос. Я новичок в WCF conecpts, мне, вероятно, не хватает какого-то секрета, чтобы сделать эту работу.

Пожалуйста, предложите любые идеи!

Что я уже пробовал:

Пример кода, это базовая версия того, что я хочу сделать.

Мне нужен объект cls2, который уже выполнил Add (), таким образом, num1 & num2 обновляются, чтобы быть полученным на стороне сервиса с правильными значениями Add (), такими как 100 & 200. ImgProcessingConnector() обрабатывает все данные для подключения к сервису.

клиент WCF

public Form1()
    {
        InitializeComponent();
        cls2 = new Class2();            
    }

    private void button1_Click(object sender, EventArgs e)
    {
        byte[] cls2Byted = Class1.SerializedtoByte(cls2);

        ImgProcessingConnector.Instance().PerformAction(cls2Byted);
    }

    Class2 cls2 = null;


служба WCF

public class ImageProcessingWCFService : IImageProcessingWCFService
{
    public ImageProcessingWCFService()
    {

    }

    public bool PerformAction(byte[] cls2Byted)
    {
        Class2 cls2 = Class1.DeSerializedfromByte(cls2Byted) as Class2;

        cls2.Subtract();

        return true;
    }
}

Класс2

[Serializable]
public class Class2 : ISerializable
{
    public Class2()
    {
        Add();
    }

    public Class2(SerializationInfo info, StreamingContext context)
    {

    }

    public void Add()
    {
        num1 = 50 + 50;
        num2 = 100 + 100;
    }

    public void Subtract()
    {
        num1 = 50 - 50;
        num2 = 100 - 100;
    }

    int num1;
    int num2;

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        //nothing to do send ALL.
    }
}

johannesnestler

просто используйте сериализатор datacontract WCF default (просто не делайте ничего особенного в своем DTO-классе) - так что все должно вести себя естественно. Почему вы придумали (старую) Сериализуемую идею…

1 Ответов

Рейтинг:
1

Maciej Los

Кажется, вы не понимаете, что именно Сериализация[^] есть...

Объект для сериализации/десериализации должен иметь по крайней мере один открытый член. Но Class2 у него нет ни одного общественного члена!
Видеть: Интерфейс ISerializable (Системы.Во время выполнения.Сериализация) | Microsoft Docs[^]

void Main()
{
	Class2 t = new Class2();
	t.num1 = 50;
	t.num2 = 100;
	Console.WriteLine("Initial values of class2: num1={0} | num2={1}", t.num1, t.num2);
	t.num2 = t.Add();
	Console.WriteLine("After using Add() method: num1={0} | num2={1}", t.num1, t.num2);

	string sFile = @"D:\tmp.data";
	IFormatter formatter = new BinaryFormatter();
	bool retVal = SerializeClass(sFile, formatter, t);
	if(retVal)
	{
		Console.WriteLine("Class2 has been sucesfully serialized!");
		t = DeserializeClass(sFile, formatter);
		if(t!=null)
		{
			Console.WriteLine("Class2 has been sucesfully deserialized!");
			Console.WriteLine("num1={0} | num2={1}", t.num1, t.num2);
			t.num2 = t.Subtract();
			Console.WriteLine("After Subtract() method: num1={0} | num2={1}", t.num1, t.num2);
		}
	}
}

//methods used in Main:
public bool SerializeClass(string fileName, IFormatter formatter, Class2 c)
{
	bool retVal = true;
    try
	{
		FileStream s = new FileStream(fileName , FileMode.Create);
	    formatter.Serialize(s, c);
		s.Close();
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);
		retVal = false;
	}
	
	return retVal;
}


public Class2 DeserializeClass(string fileName, IFormatter formatter)
{
	Class2 c = new Class2();
    try
	{
    FileStream s = new FileStream(fileName, FileMode.Open);
    c = (Class2)formatter.Deserialize(s);
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);
	}
	return c;
} 

// Class2 definition
[Serializable]
public class Class2 : ISerializable
{

    public int num1 = 0;
    public int num2 = 0;
	
	public Class2()
    {
        //empty constructor is required to compile
    }

    public int Add()
    {
        return num1 + num2;
    }

    public int Subtract()
    {
        return num2 - num1;
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("num1", num1, typeof(int));
		info.AddValue("num2", num2, typeof(int));
    }
	
	public Class2(SerializationInfo info, StreamingContext context)
    {
        // Reset the property value using the GetValue method.
        num1 = (int)info.GetValue("num1", typeof(int));
		num2 = (int)info.GetValue("num2", typeof(int));
    }


}