protobuf-net multiple derived contracts - c#

I have the following base class:
[ProtoContract]
public class Packet
{
[ProtoMember(1)]
public int Id { get; set; }
}
This class will be derived by 10+ other classes. My question is how should I assign ProtoInclude attributes?
Is this a good solution or not?
[ProtoContract]
[ProtoInclude(20, typeof(NotifyClientBalance))]
[ProtoInclude(21, typeof(IsAlive))]
[ProtoInclude(22, typeof(TransactionConfirmation))]
...
public class Packet
{
[ProtoMember(1)]
public int Id { get; set; }
}
Is there a better alternative? How should I assign tags to ProtoInclude? Everything's unclear for me and there's not a good documentation on the matter.
Thanks
P.S.
Is ProtoInclude portable across different platforms? I'm interested in Python in particular.
Thanks again :)

For use within protobuf-net, that approach is fine. The numbers are nice and low, which keeps it efficient.
Inheritance is not part of the protobuf specification, so no this is not portable between platforms - at least, not as inheritance. It is portable in terms of getting the data back. It maps to something like:
message Packet {
optional int id = 1;
optional NotifyClientBalance balance = 20;
// ...
}
message NotifyClientBalance {...}
//...
Or just use Serializer.GetProto<T>() to export the schema as .proto

Related

Design Pattern to use for customizable/extendable classes with constructors

Starting with the use case.
Let's consider the base for this questions is a big framework and implementations of business objects of some software.
This software hast to be customized quite regularly, so it would be preferred that most of the C# objects are extendable and logic can be overriden. Even "model data".
The goal would be to be able to write code, create objects with input parameters - that may create more objects etc - and you don't have to think about whether those objects have derived implementations in any way. The derived classes will be used automatically.
For ease of uses a typesafe way to create the objects would be preferred as well.
A quick example:
public class OrderModel
{
public int Id { get; set; }
public string Status { get; set; }
}
public class CustomOrderModel : OrderModel
{
public string AdditionalData { get; set; }
}
public class StockFinder
{
public Article Article { get; }
public StockFinder(Article article)
{
Article = article;
}
public virtual double GetInternalStock() { /*...*/ }
public virtual double GetFreeStock() { /*...*/ }
}
public class CustomStockFinder : StockFinder
{
public bool UsePremiumAvailability { get; }
public CustomStockFinder(Article article, bool usePremiumAvailability)
: base(article)
{
UsePremiumAvailability = usePremiumAvailability;
}
protected CustomStockFinder(Article article) : this(article, false) { } // For compatibility (?)
public override double GetFreeStock() { /*...*/ }
}
In both cases I wanna do stuff like this
var resp = Factory.Create<OrderModel>(); // Creates a CustomOrderModel internally
// Generic
var finderGeneric = Factory.Create<StockFinder>(someArticle);
// Typesafe?
var finderTypesafe1 = Factory.StockFinder.Create(someArticle); // GetFreeStock() uses the new implementation
var finderTypesafe2 = Factory.StockFinder.Create(someArticle, true); // Returns the custom class already
Automatically generating and compiling C# code on build is not a big issue and could be done.
Usage of Reflection to call constructors is okay, if need be.
It's less about how complicating some code generation logic, written code analyzers, internal factories, builders etc are, and more about how "easy" and understandable the framework solution will be on a daily basis, to write classes and create those objects.
I thought about tagging the relevant classes with Attributes and then generating a typesafe factory class automatically on build step. Not so sure about naming conflicts, or references that might be needed to compile, as the constructor parameters could be anything.
Also, custom classes could have different constructors, so they should be compatible at each place in default code where they might be constructed already, but still create the custom object. In the custom code then you should be able to use the full custom constructor.
I am currently considering several different cases and possibilities, and can't seem to find a good solution. Maybe I am missing some kind of design pattern, or am not able to look outside of my bubble.
What would be the best design pattern or coding be to implement use cases like this?

Library Input Data via Interface

We are having issues with a pattern, that is emerging in our C# solution.
Initial idea:
We have a set of features (mostly calculations), that are needed in several projects. We imagined our solution to be modular - each feature implemented as a class library which can than be referenced as a .dll in other projects.
First Issue:
What happened was, that libraries had classes, that specified the input data needed for doing the math. As a single library could be used in a number of projects we ended up coding mappings for each project, that ported the projects domain objects to the input data classes. This was tedious, as we were mostly doing a one-to-one conversion - the classes were basically the same.
Idea:
We figured that we would solve our problem with using interfaces instead of classes to specify our input data. That way we could simply label our domain classes with interfaces and we wouldn't have to do the mappings anymore.
Current Issue:
We now have a complete mayhem with interface definitions and the use of these interfaces in calculation methods. E.g.
public interface ILevel2Child
{
}
public interface ILevel1Child<TLevel2Child>
where TLevel2Child : ILevel2Child
{
List<TLevel2Child> Children { get; }
}
public interface IParent<TLevel1Child, TLevel2Child>
where TLevel1Child: ILevel1Child<ILevel2Child>
where TLevel2Child: ILevel2Child
{
List<TLevel1Child> Children { get; }
}
When we end up using the IParent interface in a method or interface, we keep dragging these insanely long signatures along.
Questions:
Was our idea of using interfaces bad to begin with?
If not, is something wrong with the way we specify our interfaces?
If still not, is there any way we can stop this insane signature pattern?
Additional explanation:
We started with
public interface ILevel2Child
{
}
public interface ILevel1Child
{
List<ILevel2Child> Children { get; }
}
public interface IParent
{
List<ILevel1Child> Children { get; }
}
but that prevented us from doing
public class Level2Child : ILevel2Child
{
}
public class Level1Child : ILevel1Child
{
List<Level2Child> Children { get; }
}
public class Parent : IParent
{
List<Level1Child> Children { get; }
}
and that was not acceptable.

Proto-buf .NET Serialization of complex inheritance interfaces

I would like to serialize for classes which do implement several interfaces some inheriting from the same base interface. Currently i use the BinaryFormatter, but i would love to use proto-buf .NET. But i think currently i would face issues similar to this described problem:
how to serialize a class implements two interfaces who have same based interface
The only possible solution i currently think of would be a wrapper around my classes which serializes a simpler data class which i use to create my complex classes.
Let me try to explain it further, like in the cited example i have a structure like this:
public interface IProduct
{
string SomeMethod();
}
public interface ISimpleProduct : IProduct
{
int SomeProperty { get; }
}
public interface IConstructionProduct : IProduct
{
int AnotherProperty {get;
}
public class ConcreteProduct : ISimpleProduct , IConstructionProduct
{
int SomeProperty {get; set;}
int AnotherProperty {get; set;}
string SomeMethod()
{
return "A concrete Product";
}
}
Now i wish to serialize ConcreteProduct, as i thought this is not possible currently in proto-buf .net i was considering to have a wrapper data class, like this:
public class ProductData
{
int[] PropertyValues { get; set;}
}
and to add to the IProductInterface a method to build each concrete product, like
public interface IProduct
{
string SomeMethod();
IProduct BuildProduct(ProductData data);
ProductData ToData();
}
Of course ProductData would be more sophisticated in reality but just for the concept. I would serialize now ProductData. I would not like to change the interface setup in the Product ConcreteProduct class as these interfaces are needed for further stuff later on. What i like about this approach, that issues with extensions could be dealt with in the BuildProduct implementations.
And again, i am a newbie, so if anything is just plain nonsense, sorry for that and correct me.
# Marc, i know you are author, thx a lot for that stuff, but more for other posts (i am not using proto-buf yet though) for example on DataTable stuff, already your post about the autogenerate columns saved a lot of time for me.
That sounds like you're going for the union types approach. You want to make a single serialization format that fits all your products. Additionally, you want each of your products to map to that union type and map back.
So you're remaining concern is on how to do the mapping. Honestly, I don't think you'll be happy in the long run with these two methods in the IProduct interface. And I hope you're aware that you need to deal with the problem of deserialization: Which type do you actually instantiate? Let me put it this way: With your code, you'll have to call new ConcreteProduct().BuildProduct(data) to get your ConcreteProduct. And the question is: How do you know it's a ConcreteProduct that you have to instantiate? The code that wants to call BuildProduct needs to know this! You could cut those methods and create a separate infrastructure for your mapping tasks. Here's what a factory method pattern would look like for this kind of problem:
public interface IProductMapper {
IProduct Unmap(ProductData data);
ProductData Map(IProduct product);
}
public static class ProductMapperFactory {
public static IProductMapper GetMapper(ProductData data) {
if (data.Type == "ConcreteProduct") return new ConcreteProductMapper();
else if ...
}
public static IProductMapper GetMapper(IProduct product) {
if (product is ConcreteProduct) return new ConcreteProductMapper();
else if ...
}
}
public class ConcreteProductMapper : IProductMapper {
public IProduct Unmap(ProductData data) {
var product = new ConcreteProduct();
// map properties
return product;
}
public ProductData Map(IProduct data) {
var data = new ProductData();
// map data
return data;
}
}
You see, the crucial line is data.Type == "ConcreteProduct": Somehow you must specify the kind of product in the data in order to know which kind of product to instantiate when mapping back from the union type.
Another difficulty that I see with union types in general is de/serialization of object graphs. Since you have your own serialization types, you need to write your own code to de/compose object graphs. If you're a newbie as you say, that'll probably put you into a world of hurt (or world of learning if you prefer :-p).
In any case, does it really need to be interfaces that you want to de/serialize? Would it be possible to instead create a class hierarchy where you're starting from a Product base class from which all other products derive and which carries the necessary includes. I assume this would create less troubles (with protobuf at least).
And finally, the master question: Why do you want to switch from the BinaryFormatter to protobuf exactly?

Should entities implement interfaces?

I personally don't have my entities implement interfaces. For a Task class I wouldn't have ITask that just had the same properties defined on it.
I've seen it done a few times though, so I'm wondering where that advice comes from, and what benefits you get from it.
If you're using an ORM then the argument that says "I can change my data access" is irrelevent, so what other reason is there for doing this?
UPDATE:
A good point was made in the comments about INotifyPropertyChanged. That wasn't my point though - I'm talking about having something like this:
public interface ITask
{
int Id { get; set; }
string Description { get; set; }
}
public class Task : ITask
{
public int Id { get; set; }
public string Description { get; set; }
}
I went down this road once (interfaces for value objects). It was a royal pain in the backside, I recommended against it. The common arguments for it are:
Mocking:
They are value objects. Nought to mock. Plus mocking ends up being a large pain than either writing a builder (in Java) or using the named arguments stuff in C#.
Readonly views:
I must admit I still prefer to make something immutable by default, only making it mutable if absolutely required.
Hidden functionality:
Generally scope has covered this one for me.
The major benefit of this is that it is a way of exposing your entity as a "read-only" version (as long as your interface does not expose setters of course).
We're doing quite a bit of unit testing and so often want to mock out things we're not testing. Although I don't like it, we've ended up using interfaces all over the place because it makes it a lot easier to mock things.
In theory most of the mocking frameworks can mock normal classes too, but in practice this has caused us issues because we sometimes do clever things with reflection and the type of the mocked class isn't the same as the original. So doing:
var myTask = MyIoCProvider.Get<Task>();
var taskType = typeof(myTask);
Was unpredictable. Whereas:
var myTask = MyIoCProvider.Get<ITask>();
var taskType = typeof(myTask);
Gives you as taskType that IS definitely derived from ITask.
So interfaces just give us a way of making our system more mockable.
If you were thinking in terms of using DomainEvents than data structures such as the task really do need to implement an interface
public interface IDomainEvent
{
Guid EventId { get; }
Guid TriggeredByEvent { get; }
DateTime Created { get; }
}
public class OrderCancelledEvent : IDomainEvent
{
Guid EventId { get; set; }
Guid TriggeredByEvent { get; set; }
DateTime Created { get; set; }
// And now for the specific bit
int OrderId { get; set; }
}
Or similarly if you have a common data access layer that may need to take in a standard base class of IEntity but I wouldn't have an interface for each type if it is just a data structure as you describe in your post.
When you are handling Domain Objects that actually expose behaviour you may then want to have an interface for unit testing.
I think some programmers just use interfaces, because they heard interfaces are good so they ended using them everywhere without thinking about actual pros and cons.
Me personally, I never use interfaces for entities that only represent a piece of data like db row for example.

protobuf-net and interface support

This question directly in large part to the protobuf-net maintainer(s) but anyone else please comment.
I was trying to serialize a class that contains a property which has an interface type, ie:
[DataContract]
public class SampleDataClass
{
[DataMember(Order=1)]
public int Field1 { get; set; }
[DataMember(Order = 2)]
public IPayload Payload { get; set; }
}
[ProtoContract]
[ProtoInclude(1, typeof(Payload))]
public interface IPayload
{
int Field4 { get; set; }
}
[DataContract]
public class Payload : IPayload
{
[DataMember(Order = 1)]
public int Field4 { get; set; }
}
I have managed to get this to work by changing the source of v1 of protobuf-net.
I did not see any problem with this approach as long as ProtoInclude is defined for the interface.
Clearly to get this to compile I had to allow ProtoContract and ProtoInclude to be decorated on interfaces, plus a few other changes here and there. (note, I would have used DataContract/KnownType however these attributes are also not able to be decorated on interfaces)
Can you please comment on possible shortcomings?
The main glitch I can see is that in terms of payload this moves the data into a sub-message. I have some similar designs around v2 that hopefully get around this, keeping most values in the primary message. For sanity reasons, I mainly had just v2 in mind for this change (since the two implementations would be separate, and v2 has a much better type model).
However, it should be possible to support both modes of use. If you want to send it as a patch for v1 (with the same license etc) I'd happily take a look :)
This is available as a standard feature of v2

Categories

Resources