Task: Serialize a list of objects into a byte[] using protobuf.
Without reflection all is good
.proto
message MyObject{
int32 id = 1;
int32 value = 2;
}
message MyObjects {
repeated MyObject objects = 1;
}
.cs
public static byte[] ToByteArray(List<MyObject> obj) {
var objects = new MyObjects {
Objects = {obj}
};
return objects.ToByteArray();
}
Since I need to serialize many different types in this way, I want to write a universal method using reflection.
Problem: Protobuf itself generates entities and properties for them, but it does not create a setter for RepeatedField, which means that I can not set the value using GetProperty("Objects")?.SetValue(objects, obj)
. System.ArgumentException: Set Method not found for 'Objects'
.cs (protobuf generated)
public pbc::RepeatedField<global::Test.MyObject> Objects {
get { return objects_; }
}
.cs
public static byte[] ToByteArray<T, E>(List<T> obj) where T : IMessage where E : IMessage {
var objects = Activator.CreateInstance<E>();
objects.GetType().GetProperty("Objects")?.SetValue(objects, obj);
return objects.ToByteArray();
}
Question: How to use reflection to set values for a property during object creation, just as I do it without reflection?
How to write this "new MyObjects {Objects = {obj}};
(where obj: IEnumerable)" using reflection
Various conclusions:
- I noticed that filling properties that do not have a setter is only possible for collections and only when creating an object.
- Most likely I need an alternative way to instantiate the class. Activator.CreateInstance() is not fulfilling my task.
Aucun commentaire:
Enregistrer un commentaire