Git Product home page Git Product logo

cslageneratorserialization's People

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

cslageneratorserialization's Issues

Register Support for Custom Types

If a user adds a type to a PropertyInfo<> that CSLA's MobileFormatter doesn't support (e.g. PropertyInfo<MyCustomStruct>), it'll fail. Same with this SG serializer. There may be a way to do this though with IoC support. The idea is that a user would register (probably as a singleton) key-value pairs to a SerializationTypes<TType, (TSerializer, TDeserializer)> instance, and the SG would gen code to reach into the IoC, grab that instance, and call the serializer or deserializer (the values are basically delegates that get a reference to the context).

Use `[AutoSerializable]` Instead

There's a discussion debating the future usage of [Serializable]. While it makes sense, SGs work well if you can target an attribute. I noticed there's an [AutoSerializable] attribute in CSLA for ... some reason. Maybe the generator targets that instead? Or should the library just define its own?

Support Other CSLA Stereotypes

These types are currently not supported by the generator. It's unclear if they really need it, as they're pretty specialized and may not have much usage in modern .NET applications:

  • ReadOnlyBindingListBase
  • BusinessBindingListBase
  • DynamicListBase
  • DynamicBindingListBase
  • MobileDictionary
  • MobileList

Move BO Serialization To Contexts

Right now I'm generating the code to handle serialization for BOs. It's not much, but it's repeated code that I could move into the reader and writer contexts. Then, I could change the gen'd code to call these methods in one line, which should hopefully simplify things.

In GeneratorFormatterWriterContext:

public void Write(IGeneratorSerializable value, bool isNotSealed = false)
{
	if (value is not null)
	{
		(var isReferenceDuplicate, var referenceId) = this.GetReference(value);

		if (isReferenceDuplicate)
		{
			this.Writer.Write((byte)SerializationState.Duplicate);
			this.Writer.Write(referenceId);
		}
		else
		{
			this.Writer.Write((byte)SerializationState.Value);

			if (isNotSealed)
			{
				var valueTypeName = value.GetType().AssemblyQualifiedName!;
				(var isTypeNameDuplicate, var typeNameId) = this.GetTypeName(valueTypeName);

				if (isTypeNameDuplicate)
				{
					this.Writer.Write((byte)SerializationState.Duplicate);
					this.Writer.Write(typeNameId);
				}
				else
				{
					this.Writer.Write((byte)SerializationState.Value);
					this.Writer.Write(valueTypeName);
				}
			}

			value.SetState(this);
		}
	}
	else
	{
		this.Writer.Write((byte)SerializationState.Null);
	}
}

This would be called like this:

context.Write(this.ReadProperty<ChildPropertiesData>(ParentPropertiesData.ChildContentsProperty));

In GeneratorFormatterReaderContext:

public void Read<T>(Action<T> propertyLoader, bool isNotSealed = false)
{
	switch (this.Reader.ReadStateValue())
	{
		case SerializationState.Duplicate:
			propertyLoader((T)this.GetReference(this.Reader.ReadInt32()));
			break;
		case SerializationState.Value:
			T newValue;

			if (isNotSealed)
			{
				if (this.Reader.ReadStateValue() == SerializationState.Duplicate)
				{
					newValue = this.CreateInstance<T>(this.GetTypeName(this.Reader.ReadInt32()))!;
				}
				else
				{
					var newValueTypeName = this.Reader.ReadString();
					this.AddTypeName(newValueTypeName);
					newValue = this.CreateInstance<T>(newValueTypeName)!;
				}
			}
			else
			{
				newValue = this.CreateInstance<T>()!;
			}

			((IGeneratorSerializable)newValue).GetState(this);
			propertyLoader(newValue);
			this.AddReference(newValue);
			break;
		case SerializationState.Null:
			break;
	}
}

This would be called like this:

context.Read<ChildPropertiesData>(_ => this.LoadProperty(ParentPropertiesData.ChildContentsProperty, _));

I'm not entirely thrilled with the delegate usage here, but, it does make the call to LoadProperty() optimal. Right now, calling GetReference() always returns an object (because it has to), but then passing that into LoadProperty() as an object causes LoadPropertyByReflection() to be called in CSLA, and that's not idea.

This may allow the methods around the "duplicate" dictionaries in the contexts to be private. Though I need to be careful with that, especially with the deleted list field for lists.

Allow for Custom Serialization

Right now, there's no way for a BO to add custom state to the serialization process. One idea would be to add two methods with DIMs to IGeneratorSerializable, but the problem is that DIMs are not supported in .NET Standard. So, I either create another package that this one references, or I generate the interface (and anything relying on it) during SG initialization.

This idea is sketched out in sharplab.io here

using System;
using System.IO;

Roundtrip(new Normal());
Console.WriteLine();
Roundtrip(new Custom());

static void Roundtrip(ISerialize target)
{
    Console.WriteLine(target.GetType().FullName);
    target.Deserialize(null!);
    target.CustomDeserialize(null!);    
    target.Serialize(null!);
    target.CustomSerialize(null!);
}

public interface ISerialize
{
    void Deserialize(BinaryReader reader);
    void CustomDeserialize(BinaryReader reader) { Console.WriteLine("ISerialize.CustomDeserialize()"); }
    void Serialize(BinaryWriter writer);
    void CustomSerialize(BinaryWriter writer) { Console.WriteLine("ISerialize.CustomSerialize()"); }
}

public class Normal
    : ISerialize
{
    void ISerialize.Deserialize(BinaryReader reader) { Console.WriteLine("Normal.Deserialize()"); }
    void ISerialize.Serialize(BinaryWriter writer) { Console.WriteLine("Normal.Serialize()"); }
}

public class Custom
    : ISerialize
{
    void ISerialize.Deserialize(BinaryReader reader) { Console.WriteLine("Custom.Deserialize()"); }
    void ISerialize.CustomDeserialize(BinaryReader reader) { Console.WriteLine("Custom.CustomDeserialize()"); }
    void ISerialize.Serialize(BinaryWriter writer) { Console.WriteLine("Custom.Serialize()"); }
    void ISerialize.CustomSerialize(BinaryWriter writer) { Console.WriteLine("Custom.CustomSerialize()"); }
}

Add Duplication Logic for Custom Serializable Types

For custom serialization, if the target type is a reference type, then check to see if it's a duplicate first, and then call the user's custom implementation if it's not. This will give the same behavior for handling duplicate references within a graph that currently exists in this serializer and MobileFormatter as well.

Pass Custom Context to Custom Handlers

I may want to pass in the contexts to the custom handlers, rather than the readers and writers. Reason is, it may be possible that a custom handler needs to invoke another custom handler.

Rename `isNotSealed` on Context Methods

Change isNotSealed to isSealed in both GeneratorFormatterWriterContext and GeneratorFormatterReaderContext, and flip the bit when calling it. It just looks weird to have it be "negative" :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.