Proto-buf .NET Serialization of complex inheritance interfaces - c#

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?

Related

How can I make my code extendable for future use

I am trying to structure my code so that I can easily extend it in the future, however I think I am overthinking things and struggling to accomplish this.
My scenario is:
Based upon some data being passed to me I need to generate a class.
The class that I need to generate is not similar in nature to any of the other classes.
For example I have several classes that can be created:
public class File1{
public string Name {get;set;}
// etc...
}
public class File2{
public int ID {get;set;}
// etc...
}
public class File3{
public string MyType {get;set;}
// etc...
}
In my main class I have:
switch (myExtension)
{
case ".abc":
ProcessABC(myContents);
break;
case ".def":
ProcessDEF(myContents);
break;
case ".ghi":
ProcessGHIL(myContents);
break;
//etc...
}
I have tried creating an interface with a common method:
public ProccessStuff(data);
but I don't think that will work since I don't have a common return type.
Then I thought about an abstract class, but then it seems I'll be pushing a lot of work into that abstract class.
public abstract class MyAbstractClass
{
public void ProcessStuff(string data)
{
// Parse the data into an object
// Update some DB fields
// Log some data
}
}
Am I on the right path with just creating an abstract class to handle all of my logic?
You're saying the classes don't have any similarities. But that's not actually true - they all take a string to do some processing, and it's exactly this that you want shared between the classes.
Make an interface, IDataProcessor (or something). There, have a single method - void Process(string). The file classes will implement the method in a way they require.
This changes your main classes switch to a simple
IDataProcessor actualDataProcessor = ...;
actualDataProcessor.Process(myContents);
Of course, you still need some way to create the proper IDataProcessor based on e.g. the extension. Depending on your exact needs, a simple Dictionary<string, Func<IDataProcessor>> might be quite enough. Otherwise, there's plenty of other ways to bind classes more dynamically if you so desire, or use an explicit factory class.
Have you tried using generics?
Here is an example :
public void Process<T>(string contents)
where T : IProcessStuff, new ()
{
// Common work to do here
// ...
// Specific processing stuff
T t = new T();
t.ProcessStuf(contents);
}
public interface IProcessStuff
{
void ProcessStuf(string contents);
}

Accepting multiple similar entities in a Method - Elegant solution

I have two data entities, which are almost similar, design is something like:
public Class Entity1 : Base
{
public int layerId;
public List<int> Groups;
}
Difference is Entity1 has an extra collection of integer Groups
public Class Entity2 : Base
{
public int layerId;
}
These entities are filled as an input from UI using Json, I need to pass them to a processing method, which gives the same Output entity. Method has a logic to handle if List<int> Groups is null, I need to create a method which is capable of handling each of the input in an elegant manner. I cannot just use only Entity1, since they are two different functional inputs for different business process, so using Entity1 as direct replacement would be a mis-representation
Instead of creating overload of the function, I can think of following options:
Use object type as input and typecast in the function internally
I think we can similarly use dynamic types, but solution will be similar as above, it will not be a clean solution in either case, along with the switch-case mess.
What I am currently doing is processing method is like this:
public OuputEntity ProcessMethod(Entity 1)
{
// Data Processing
}
I have created a constructor of Entity1, that takes Entity2 as Input.
Any suggestion to create an elegant solution, which can have multiple such entities. May be using generic, where we use a Func delegate to create a common type out of two or more entities, which is almost similar to what I have currently done. Something like:
Func<T,Entity1>
Thus use Entity1 output for further processing in the logic.
I need to create a method which is capable of handling each of the input in an elegant manner
Create an Interface, or a contract so to speak, where each entity adheres to the particular design. That way common functionality can be processed in a similar manner. Subsequently each difference is expressed in other interfaces and testing for that interface sis done and the differences handled as such.
May be using generic,
Generic types can be tested against interfaces and a clean method of operations hence follows suit.
For example say we have two entities that both have Name properties as string, but one has an Order property. So we define the common interface
public interface IName
{
string Name { get; set; }
string FullName { get; }
}
public interface IOrder
{
decimal Amount { get; set; }
}
So once we have our two entities of EntityName and EntityOrder we can add the interfaces to them, usually using the Partial class definition such as when EF creates them on the fly:
public partial class EntityName : IName
{
// Nothing to do EntityName already defines public string Name { get; set; }
public string FullName { get { return "Person: " + Name; }}
}
public partial class EntityOrder : IName, IOrder
{
// Nothing to do Entity Order already defines public string Name { get; set; }
// and Amount.
public string FullName { get { return "Order: " + Name; } }
}
Then we can process each of them together in the same method
public void Process(IName entity)
{
LogOperation( entity.FullName );
// If we have an order process it uniquely
var order = entity as IOrder;
if (order != null)
{
LogOperation( "Order: " + order.Amount.ToString() );
}
}
Generic methods can enforce an interface(s) such as:
public void Process<T>(T entity) where T : IName
{
// Same as before but we are ensured that only elements of IName
// are used as enforced by the compiler.
}
Just create generic method that will do this work for you:
List<OuputEntity> MyMethod<T>(T value) where T : Base
// adding this constraint ensures that T is of type that is derived from Base type
{
List<OutputEntity> result = new List<OutputEntity>();
// some processing logic here like ...
return result;
}
var resultForEntity1 = MyMethod<Entity1>();
var resultForEntity2 = MyMethod<Entity2>();
P.S. check my answer for this question as you may find it useful too:
map string to entity for using with generic method
You probably want to implement an interface or an abstract class.
From MSDN
If you anticipate creating multiple versions of your component, create
an abstract class. Abstract classes provide a simple and easy way to
version your components. By updating the base class, all inheriting
classes are automatically updated with the change. Interfaces, on the
other hand, cannot be changed once created. If a new version of an
interface is required, you must create a whole new interface.
If the functionality you are creating will be useful across a wide range of
disparate objects, use an interface. Abstract classes should be used
primarily for objects that are closely related, whereas interfaces are
best suited for providing common functionality to unrelated classes.
If you are designing small, concise bits of functionality, use
interfaces. If you are designing large functional units, use an
abstract class.
If you want to provide common, implemented
functionality among all implementations of your component, use an
abstract class. Abstract classes allow you to partially implement your
class, whereas interfaces contain no implementation for any members.
Abstract Class Example
Cat and Dog can both inherit from abstract class Animal, and this abstract base class will implement a method void Breathe() which all animals will thus do in exactly the same fashion. (You might make this method virtual so that you can override it for certain animals, like Fish, which does not breath the same as most animals).
Interface Example
All animals can be fed, so you'll create an interface called IFeedable and have Animal implement that. Only Dog and Horse are nice enough though to implement ILikeable - You'll not implement this on the base class, since this does not apply to Cat.

Creating a Generic Save() Method for Models

I have a fairly simple system, and for the purposes of this question there are essentially three parts: Models, Repositories, Application Code.
At the core are the models. Let's use a simple contrived example:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
In that same project is a generic repository interface. At its simplest:
public interface IRepository<T>
{
T Save(T model);
}
Implementations of that interface are in a separate project and injected with StructureMap. For simplicity:
public class PersonRepository : IRepository<Person>
{
public Person Save(Person model)
{
throw new NotImplementedException("I got to the save method!");
// In the repository methods I would interact with the database, or
// potentially with some other service for data persistence. For
// now I'm just using LINQ to SQL to a single database, but in the
// future there will be more databases, external services, etc. all
// abstracted behind here.
}
}
So, in application code, if I wanted to save a model I would do this:
var rep = IoCFactory.Current.Container.GetInstance<IRepository<Person>>();
myPerson = rep.Save(myPerson);
Simple enough, but it feels like it could be automated a lot. That pattern holds throughout the application code, so what I'm looking to do is create a single generic Save() on all models which would just be a shorthand call to the above application code. That way one would need only call:
myPerson.Save();
But I can't seem to figure out a way to do it. Maybe it's deceptively simple and I'm just not looking at it from the correct angle. At first I tried creating an empty ISaveableModel<T> interface and intended to have each "save-able" model implement it, then for the single generic Save() method I would have an extension on the interface:
public static void Save<T>(this ISaveableModel<T> model)
{
var rep = IoCFactory.Current.Container.GetInstance<IRepository<T>>();
model = rep.Save(model);
}
But it tells me that rep.Save(model) has invalid arguments. It seems that it's not wiring up the type inference as I'd hoped it would. I tried a similar approach with a BaseModel<T> class from which models would inherit:
public class BaseModel<T>
{
public void Save()
{
this = IoCFactory.Current.Container.GetInstance<IRepository<T>>().Save(this);
}
}
But the compiler error is the same. Is there a way to achieve what I'm trying to achieve? I'm very flexible on the design, so if I'm going about something all wrong on an architectural level then I have room to step back and change the big picture.
Would a generic extension method solve it?
public static T Save<T>(this T current)
{
var rep = IoCFactory.Current.Container.GetInstance<IRepository<T>>();
rep.Save(current);
}
You can then constrain it to your ISaveableModel<T> interface. Return type above not implemented, but you can put it to a boolean or status flag, whatever.
In both approaches, the parameter to the Save() function is not of type T. In the first one, it is ISaveableModel<T>, and in the second, it is BaseModel<T>. Since the repository is a generic based on T, Save method will expect a variable of type T. You can add a simple cast to T before you call Save to fix it.
Alternatively, your IRepostory<T> can be changed to
public interface IRepository<T>
{
T Save(ISaveableModel<T> model);
}
which makes more sense.

Anybody have a clever way to treat a DTO as more of an OO class?

I have a set of DataContracts that are serialzed through WCF.
Please note this is a very simplified example.
[DataContract]
public class MyData
{
[DataMember]
public List<int> MyList
{
get;
set;
}
}
I would like to use object oriented design so that the server and client aren't creating any unnecessary dependencies. For example, I would like to encapsulate a list so that the user can't directly modify it.
Ideally, I would like the class to look like this if it wasn't a DTO.
public class MyData
{
private List<int> _list = new List<int>();
public IEnumerable<int> MyList
{
get
{
return _list;
}
}
public void AddItem( int value )
{
_list.Add( value );
}
}
I am using the same C# assembly from both the service and the client. So I can add non-DataMember methods, but I'm not sure if that is a good approach. It doesn't smell quite right to me.
Does anybody have a clever way of treating DTO classes more like objects instead of simple serializable structures?
How about having DTO versions of your logic class which are used solely for the purpose of message passing?
That way, you can put all the methods and properties on your logic class as necessary without having to worry about what the user has access to when it's passed over the wire. There are many ways you can go about this, for instance:
you can implement some method on your logic class to return the DTO
public class Player
{
// methods that do interesting things here
...
public string Name { get; set; }
public PlayerDTO ToTransport()
{
return new PlayerDTO { Name = Name, ... };
}
}
[DataContract]
public class PlayerDTO
{
[DataMember]
public string Name { get; set; }
...
}
Or you can implement an explicit/implicit conversion
public class Player
{
// methods that do interesting things here
...
public string Name { get; set; }
}
[DataContract]
public class PlayerDTO
{
[DataMember]
public string Name { get; set; }
...
public static explicit operator PlayerDTO(Player player)
{
return new PlayerDTO { Name = player.Name, ... };
}
}
this lets you cast a Player object to PlayerDTO:
var player = new Player { Name = .... };
var dto = (PlayerDTO) player;
Personally, I do think having DataContract on objects which are for more than service operations is a bit of a smell, just as it would be for ORM column mappings. One somewhat limited way to make these DTOs more like true OO is to have your methods be extension methods of the DTO. You might need to do something creative if the OO version has state that needs to be captured between calls that is not inherent in the DTO object itself, though.
I do not think having methods unadorned by attributes in your DataContract's class necessarily smells. You have your service-oriented concerns on one hand (the operation and data contracts) and your object-oriented concerns on the other. What the client does with the provided data is of no concern to the service. The object-oriented issue you describe really only exists for the client.
If a client obtained Ball data from your service and it wants to Draw() it to the screen, whether or not the Ball class has a Draw() method has nothing to do with the contract between service and client. It is a contract between the api your assembly provides and those that use it. So I say, why not have a method in the assembly that is not an operation/data contract?

How can I implement an interface that can take many object types

excuse what seems like a real noobie question but how can I implement the following
public interface IViewModel {
void Map<T>();
}
public class CarViewModel : IViewModel
{
public string Color { get; private set; }
public int Tyres { get; private set; }
public CarViewModel(Car _car)
}
//this is where the problem is - there can be many differnt kind of object but I want them all to implement a Map function. I want to be able to assign the properties to incoming object. I also need to cater for IList of cars coming in that need to be populated. I suspect I am not using Generics properly
public void Map<T>(Car _car){
Color = _car.Color;
Tyres = _car.Tyres;
}
Do you mean this?
public interface IViewModel<T>
{
void Map(T domainObject);
}
public class CarViewModel : IViewModel<Car>
{
public Map(Car domainObject) { ... }
}
You say:
I suspect I am not using Generics properly
and you are correct. Additionally, you are not using polymorphism properly.
If you want to polymorphically accept several different types that all have something in common, then you need to create an interface that is the parent type of all of the types you will be using. You can do this without using any Generics at all.
What Generics (aka parametric polymorphism) gives you is a way to create one type that is parameterized by another type (and thus behaves like many different types). For example, IList<T> is parameterized by a type variable T -- then IList<string> and IList<int> are two separate types (with many possible subtypes each), but you only have to write the code once.
What are your actual requirements for this design? What are your ViewModel classes trying to accomplish?

Categories

Resources