how to add optional field to a class manually in protobuf-net - c#

In my .proto I have some messages that have optional fields. There is no native protogen for Debian so I don't have one to experiment with (too lazy to compile it myself :).
Could you tell me how to implement an optional field in a class in C#? I would like to have a function or whatever that idicate the field is set (in C++ I have something like hasfoo() ). In examples I found in the internet there is nothing like that.

It supports a number of patterns here, to help transition from other serializers. And note that there are options in the protobuf-net protogen to include such members for you automatically.
Firstly, anything null is omitted; this includes both null references and Nullable<T> for structs. So:
[ProtoMember(1)]
public int? A {get;set;}
will behave.
Another option is default values; using .NET conventions:
[ProtoMember(2), DefaultValue(17)]
public int B {get;set;}
no values of 17 will be serialized.
For more explicit control, the ShouldSerialize* pattern (from XmlSerializer) and the *Specified pattern (from DataContractSerializer) are observed, so you can do:
[ProtoMember(3)]
public string C {get;set;}
public bool ShouldSerializeC() { /* return true to serialize */ }
and
[ProtoMember(4)]
public string D {get;set;}
public bool DSpecified {get;set;} /* return true to serialize */
These can be public or private (unless you are generating a standalone serialization assembly, which requires public).
If your main classes are coming from code-gen, then a partial class is an ideal extension point, i.e.
partial class SomeType {
/* extra stuff here */
}
since you can add that in a separate code file.

Related

What is the idiomatic use case for static fields inside interfaces?

I've searched through this website for anything tagged c# static interface and found that the topic rarely comes up. Examples from other websites have been similarly unsatisfactory and I've yet to come up with anything myself. I've therefore found it difficult to think of a use case for interfaces that include static fields.
Is there any design pattern, or any other idiom, that recommends the usage of a static field inside of an interface?
Traditionally interfaces are just contracts and do not contain executable code or state information but only contain abstract instance members that must be implemented by a class or a struct. Two features introduced in C# 8.0 and C# 11 add static members to interfaces. Only the first one adds executable code to the interface and possibly with it the need to save state:
In C# 8.0 Microsoft has introduced default interface methods. It is optional for a class to implement these methods. If they are not implemented, the default implementations kick in. However, these methods are not inherited by the class and can only be called through the interface (even within the class implementing the interface).
The primary motivation is to allow extending an interface without breaking existing code.
Static fields and other members not being part of the public interface are there to support the implementation of those default interface methods. The C# language proposal for default interface methods says:
Interfaces may not contain instance state. While static fields are now permitted, instance fields are not permitted in interfaces. Instance auto-properties are not supported in interfaces, as they would implicitly declare a hidden field.
Static and private methods permit useful refactoring and organization of code used to implement the interface's public API.
Yet another feature is coming with C# 11: static virtual members in interfaces. Those must be implemented by the implementing class. They were primarily introduced to allow formulating interfaces for numeric types who have static operator methods (+, -, *, /, etc.). But they also allow to declare static factory methods. These interfaces are useful in generic type constraints.
Here is a full use case. New properties are added to an interface. To not break existing implementations, they are added with a default implementation.
Since we cannot store instance state in an interface (interfaces are not instantiated), we cannot use instance backing fields for the properties. Instead, we use a dictionary with object references as key to store the property values. (We could also use Weak References, but that's beyond the scope of this article.) The dictionary is stored in a private static field. This is comparable to how WPF stores dependency properties.
interface IUseCase
{
string Name { get; set; } // Public by default, must be implemented by the class
// New property added in a later release with a default implementation.
// Implementation by class is optional.
private static Dictionary<IUseCase, string?> _firstNames =
new(ReferenceEqualityComparer.Instance);
string? FirstName
{
get {
_firstNames.TryGetValue(this, out string? s);
return s; // s is null when TryGetValue returns false
}
set {
_firstNames[this] = value;
}
}
// New property with default implementation.
string FullName => $"{FirstName} {Name}";
}
A class created before the interface was extended implementing only the first property.
class UseCase : IUseCase
{
public UseCase(string name)
{
Name = name;
}
public string Name { get; set; }
}
Test:
IUseCase u1 = new UseCase("Doe");
u1.FirstName = "John";
IUseCase u2 = new UseCase("Poe");
u2.FirstName = "Jane";
Console.WriteLine(u1.FullName);
Console.WriteLine(u2.FullName);
Prints:
John Doe
Jane Poe
It looks like there are two main reasons such as
to store a value that must be shared among all instances
you can count some value between all instances
to avoid recreation of an instance of static field value each time
Let me show a example:
public interface IFoo
{
private static string staticField;
public static string GetStaticField()
{
if (staticField is null)
staticField = $"DateTime is {DateTime.Now}";
return staticField;
}
}
or shorter version will look like this:
public static string GetStaticField()
{
staticField ??= $"DateTime is {DateTime.Now}";
return staticField;
}
and then it can be seen that if staticField will be assigned, then it never be reassigned:
var result_1 = IFoo.GetStaticField();
Console.WriteLine(result_1);
Thread.Sleep(10000); // imitation of hard work
var result_2 = IFoo.GetStaticField();
Console.WriteLine(result_2);
Output:
DateTime is 2022.10.12 05:10
DateTime is 2022.10.12 05:10

What is the best approach or alternative to constant references?

For the purposes of this question, a 'constant reference' is a reference to an object from which you cannot call methods that modify the object or modify it's properties.
I want something like this:
Const<User> user = provider.GetUser(); // Gets a constant reference to an "User" object
var name = user.GetName(); // Ok. Doesn't modify the object
user.SetName("New value"); // <- Error. Shouldn't be able to modify the object
Ideally, I would mark with a custom attribute (e.g. [Constant]) every method of a class that doesn't modify the instance, and only those methods can be called from the constant reference. Calls to other methods would result in an error, if possible, during compile time.
The idea is I can return a read-only reference to and be sure that it will not be modified by the client.
The technique you're referring to is called "const-correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.
Alternatively, there's a much simpler solution using interfaces: because C# (and I think the CLR too) does not support const-correctness (the closest we have is the readonly field modifier) the .NET base-class-library designers added "read-only interfaces" to common mutable types to allow a object (wheather mutable or immutable) to expose its functionality via an interface that only exposes immutable operations. Some examples include IReadOnlyList<T>, IReadOnlyCollection<T>, IReadOnlyDictionary<T> - while these are all enumerable types the technique is good for singular objects too.
This design has the advantage of working in any language that supports interfaces but not const-correctness.
For each type (class, struct, etc) in your project that needs to expose data without risk of being changed - or any immutable operations then create an immutable interface.
Modify your consuming code to use these interfaces instead of the concrete type.
Like so:
Supposing we have a mutable class User and a consuming service:
public class User
{
public String UserName { get; set; }
public Byte[] PasswordHash { get; set; }
public Byte[] PasswordSalt { get; set; }
public Boolean ValidatePassword(String inputPassword)
{
Hash[] inputHash = Crypto.GetHash( inputPassword, this.PasswordSalt );
return Crypto.CompareHashes( this.PasswordHash, inputHash );
}
public void ResetSalt()
{
this.PasswordSalt = Crypto.GetRandomBytes( 16 );
}
}
public static void DoReadOnlyStuffWithUser( User user )
{
...
}
public static void WriteStuffToUser( User user )
{
...
}
Then make an immutable interface:
public interface IReadOnlyUser
{
// Note that the interfaces' properties lack setters.
String UserName { get; }
IReadOnlyList<Byte> PasswordHash { get; }
IReadOnlyList<Byte> PasswordSalt { get; }
// ValidatePassword does not mutate state so it's exposed
Boolean ValidatePassword(String inputPassword);
// But ResetSalt is not exposed because it mutates instance state
}
Then modify your User class and consumers:
public class User : IReadOnlyUser
{
// (same as before, except need to expose IReadOnlyList<Byte> versions of array properties:
IReadOnlyList<Byte> IReadOnlyUser.PasswordHash => this.PasswordHash;
IReadOnlyList<Byte> IReadOnlyUser.PasswordSalt => this.PasswordSalt;
}
public static void DoReadOnlyStuffWithUser( IReadOnlyUser user )
{
...
}
// This method still uses `User` instead of `IReadOnlyUser` because it mutates the instance.
public static void WriteStuffToUser( User user )
{
...
}
So, these are the first two ideas I initially had, but don't quite solve the problem.
Using Dynamic Objects:
The first idea I had was creating a Dynamic Object that would intercept all member invokations and throw an error if the method being called isn't marked with a [Constant] custom attribute. This approach is problematic because a) We don't have the support of the compiler to check for errors in the code (i.e. method name typos) when dealing with dynamic objects, which might lead to a lot of runtime errors; and b) I intend to use this a lot, and searching for method names by name every time a method is called might have considerable performance impact.
Using RealProxy:
My second idea was using a RealProxy to wrap the real object and validate the methods being called, but this only works with objects that inherit from MarshalByRefObject.

Jil.DeserializationException : Error occurred building a deserializer in redis cache

I'm using Redis Cache using Stack Exchange library.
I used cloudStructure library to use Redis Dictionary and Redis List.
Problem is when I try to retrieve values and if that model has a null
value for one list property it is throwing me below exception -
Jil.DeserializationException : Error occurred building a deserializer
for TestMainClass: Expected a
parameterless constructor for
System.Collections.Generic.ICollection1[TestChildClass]
---- Jil.Common.ConstructionException : Expected a parameterless constructor for
System.Collections.Generic.ICollection1[TestChildClass]
public class TestMainClass
{
public TestMainClass();
public int Id { get; set; }
public virtual ICollection<TestChildClass> Mydata { get; set; }
public string Title { get; set; }
}
public class TestChildClass
{
public TestChildClass();
public int Id { get; set; }
public string Value { get; set; }
}
Redis code for retrieve value:
RedisDictionary<int, TestMainClass> dictionary =
new RedisDictionary<int, TestMainClass>("localhost", "mylocaldictionary");
var result = await dictionary.Get(121);
What If I could not able to convert ICollection < T > into List < T >?
It might be a nice feature if the serialization library detected interfaces like ICollection<T> and IList<T> and implemented them with the concrete List<T> during deserialization, but ultimately: every feature needs to be thought of, considered (impact), designed, implemented, tested, documented and supported. It may be that the library author feels this is a great idea and should be implemented; it might not be high on the author's list, but they'd be more than happy to take a pull request; or there might be good reasons not to implement it.
In the interim, as a general rule that will solve virtually every serialization problem you will ever encounter with any library:
the moment the library doesn't work perfectly with your domain model: stop serializing your domain model - use a DTO instead
By which, I mean: create a separate class or classes that are designed with the specific choice of serializer in mind. If it wants List<T>: then use List<T>. If it wants public fields: use public fields. If it wants the types to be marked [Serializable]: mark the types [Serializable]. If it wants all type names to start with SuperMagic: then start the type name with SuperMagic. As soon as you divorce the domain model from the serialization model, all the problems go away. In addition: you can support multiple serializers in parallel, without getting into the scenario that A needs X and doesn't work with Y; B needs Y and doesn't work with X.
All you then need to do is write a few lines of code to map between the two similar models (or use libraries that do exactly that, like AutoMapper).

2 objects, exactly the same (except namespace) c#

I'm using a 3rd party's set of webservices, and I've hit a small snag. Before I manually make a method copying each property from the source to the destination, I thought I'd ask here for a better solution.
I've got 2 objects, one of type Customer.CustomerParty and one of type Appointment.CustomerParty. The CustomerParty objects are actually property and sub-oject exactly the same. But I can't cast from 1 to the other.
So, I need to find a certain person from the webservice. I can do that by calling Customer.FindCustomer(customerID) and it returns a Customer.CustomerParty object.
I need to take that person that I found and then use them a few lines down in a "CreateAppointment" request. Appointment.CreateAppointment takes an appointment object, and the appointment object contains a CustomerParty object.
However, the CustomerParty object it wants is really Appointment.CustomerParty. I've got a Customer.CustomerParty.
See what I mean? Any suggestions?
Why don't you use AutoMapper? Then you can do:
TheirCustomerPartyClass source = WebService.ItsPartyTime();
YourCustomerPartyClass converted =
Mapper.Map<TheirCustomerPartyClass, YourCustomerPartyClass>(source);
TheirCustomerPartyClass original =
Mapper.Map<YourCustomerPartyClass, TheirCustomerPartyClass>(converted);
As long as the properties are identical, you can create a really simple map like this:
Mapper.CreateMap<TheirCustomerPartyClass, YourCustomerPartyClass>();
Mapper.CreateMap<YourCustomerPartyClass, TheirCustomerPartyClass>();
This scenario is common when writing domain patterns. You essentially need to write a domain translator between the two objects. You can do this several ways, but I recommend having an overridden constructor (or a static method) in the target type that takes the service type and performs the mapping. Since they are two CLR types, you cannot directly cast from one to the other. You need to copy member-by-member.
public class ClientType
{
public string FieldOne { get; set; }
public string FieldTwo { get; set; }
public ClientType()
{
}
public ClientType( ServiceType serviceType )
{
this.FieldOne = serviceType.FieldOne;
this.FieldTwo = serviceType.FieldTwo;
}
}
Or
public static class DomainTranslator
{
public static ServiceType Translate( ClientType type )
{
return new ServiceType { FieldOne = type.FieldOne, FieldTwo = type.FieldTwo };
}
}
I'm using a 3rd party's set of
webservices...
Assuming you can't modify the classes, I'm not aware of any way you can change the casting behavior. At least, no way that isn't far, far more complicated than just writing a CustomerToAppointmentPartyTranslator() mapping function... :)
Assuming you're on a recent version of C# (3.5, I believe?), this might be a good candidate for an extension method.
Have you looked at adding a conversion operator to one of the domain classes to define an explicit cast. See the msdn documentation here.
Enjoy!
A simple and very fast way of mapping the types is using the PropertyCopy<TTarget>.CopyFrom<TSource>(TSource source)
method from the MiscUtil library as described here:
using MiscUtil.Reflection;
class A
{
public int Foo { get; set; }
}
class B
{
public int Foo { get; set; }
}
class Program
{
static void Main()
{
A a = new A();
a.Foo = 17;
B b = PropertyCopy<B>.CopyFrom(a);
bool success = b.Foo == 17; // success is true;
}
}
Two classes with exactly the same signature, in two different namespaces, are two different classes. You will not be able to implicitly convert between them if they do not explicitly state how they can be converted from one to the other using implicit or explicit operators.
There are some things you may be able to do with serialization. WCF DataContract classes on one side do not have to be the exact same type as the DataContract on the other side; they just have to have the same signature and be decorated identically. If this is true for your two objects, you can use a DataContractSerializer to "convert" the types through their DataContract decoration.
If you have control over the implementation of one class or the other, you can also define an implicit or explicit operator that will define how the other class can be converted to yours. This will probably simply return a new reference of a deep copy of the other object in your type. Because this is the case, I would define it as explicit, to make sure the conversion is only performed when you NEED it (it will be used in cases when you explicitly cast, such as myAppCustomer = (Appointment.CustomerParty)myCustCustomer;).
Even if you don't control either class, you can write an extension method, or a third class, that will perform this conversion.

Which serializer is most forgiving for changes to the serialized types in .NET?

I noticed the XmlSerializer is more forgiving to adding new members, removing existing ones, etc to the serialized types.
When I did this with the BinaryFormatter, and tried to deserialize the old data, it threw an exception.
What other alternatives are there for forgiving options, i.e. one that doesn't throw an exception just uses default values, skips them, etc?
Are protocol buffers forgiving in this regard?
You mention binary, and indeed BinaryFormatter is very brittle here. The problem is that BinaryFormatter is type and field based. Instead, you want a contract-based serializer, such as XmlSerialzier, DataContractSerializer (3.0), etc.
Or for binary, protobuf-net is a C# implementation of Google's "protocol buffers" wire format, but re-implemented along .NET lines; (note: I'm the author...).
It is (like the others) data-contract based, but instead of <CustomerName>asdasd</CustomerName> etc, it uses numeric tags to identify things instead; so:
[ProtoContract]
public class Customer {
[ProtoMember(1)]
public string Name {get;set;}
// ...
}
As you add more members you give them new unique numbers; this keeps it extensible without relying on any names etc. Plus it is very fast ;-p As with XmlSerializer, it will ignore things it doesn't expect (or it can store them for safe round-trip of unexpected data), and supports the same default things. You can even use your existing xml attributes:
[XmlType]
public class Customer {
[XmlElement(Order=1)]
public string Name {get;set;}
// ...
}
I could talk about this subject all day, so I'd better shut up before [too late].
You could inherit your class from ISerializable and define a custom GetObjectData. I haven't tested this, but such a class might be deserializable from a binary format, even if changes have since been made to the class.
EDIT
I just confirmed that this works. You can use code like the example below to explicitly define how an object is serialized and deserialized. It would then be up to you to make these methods work with older versions of your class. I tested this by serializing an instance of Cereal to a binary file, then making changes to the class and reading the file back in for deserialization.
[Serializable]
private class Cereal : ISerializable
{
public int Id { get; set; }
public string Name { get; set; }
public Cereal()
{
}
protected Cereal( SerializationInfo info, StreamingContext context)
{
Id = info.GetInt32 ( "Id" );
Name = info.GetString ( "Name" );
}
public void GetObjectData( SerializationInfo info, StreamingContext context )
{
info.AddValue ( "Id", Id );
info.AddValue ( "Name", Name );
}
}
I strongly recommend doing your own serialization so that you have well-defined file formats independent of the language schemes.
I actually find that the binary formatter is the most durable in the long run.
It provides excellent forward compatibility. That is to say, if you upgrade the file to a new version, it will not work with the old deserializer.
I generally create some simple data classes that I want to use for serialization. When i need to change the class, I implement the OnDeserialized / OnDeserializing methods. This allows the data to be upgraded.
The binary formatter does not require that you have a public setter for your properties, which to me is a big problem sometimes.
[Serializable]
public class data
{
private int m_MyInteger;
// New field
private double m_MyDouble;
[OnDeserializing]
internal void OnDeserializing(StreamingContext context)
{
// some good default value
m_MyDouble = 5;
}
public int MyInteger
{
get{ return m_MyInteger; }
set { m_MyInteger = value; }
}
}
I think the following post could help you. I also agree with others who said to write your own serializer. It is way better than generated code from xsd.exe .
See the post below:
Serialization and Deserialization into an XML file, C#
You can also look at the OptionalFieldAttribute for use with SerializableAttribute/NonSerializedAttribute and the BinaryFormatter and SoapFormatter
... version 1
[Serializable]
public class MyClass
{
public string field1;
[NonSerialized]
public string field2;
}
... version 2
[Serializable]
public class MyClass
{
public string field1;
[NonSerialized]
public string field2;
[OptionalField]
public string field3;
}

Categories

Resources