Dynamically ignore data members from getting serialized - c#

We have an existing WCF service which uses several DataContracts. We want to modify the serialization based on the device, so that when accessed from mobile devices, the service should serialize only some important data members(not all)
We have 2 options here
Create separate operation and data contracts for different types of
devices
Mess with the actual xml serialization and suppress creating
unnecessary elements based on the device
We don't want to go with the first option since it introduces a lot of redundant code problems in the future
Small research showed that we need to use IXmlSerializable and override the readXML() and writeXML() methods. But at the same time, I have seen somewhere that DataContract and IXmlSerializable should not be used together
Any example to mess with actual serialization is greatly appreciated .
[DataContract]
public class TokenMessage
{
string tokenValue;
string extraValue;
[DataMember]
public string Token
{
get { return tokenValue; }
set { tokenValue = value; }
}
[DataMember]
public string Extra
{
get { return extraValue; }
set { extraValue = value; }
}
}
Now when i access the service which returns a typical TokenMessage data contract, from a mobile device, i don't want the "Extra" data member to be serialized i.e. When I supply a different argument to the operation contract, it should be able to serialize some/all the data members(depending on the action)
PS: For now please ignore the device detection part. Lets assume we have an argument in the operation contract, which helps us identify the device

I'm not convinced that some variant of #Pranav Singh's answer isn't a better design, but that's not your question...
As you mentioned in a comments attributes in .NET are static by design. This means dynamically adding/removing [DataMember] isn't a good option. It is possible. There are options like using Reflection.Emit to recreate the instance with the meta data changes (see all the answers to Can attributes be added dynamically in C#?) but all of those routes are complicated.
I see two reasonable options:
1) Implement an IParameterInspector for the service. In the AfterCall() method you could inspect and alter the parameters being returned to the client before they are serialized. There is some work to use reflection to dynamically determine the parameter types and set their values, but its not complicated. This is the better design that enables reuse of the behavior across many contracts or services. Carlos Figueira's blog is the best source for WCF extension examples.
2) Use the [OnSerializing] and [OnSerialized] events. In the [DataContract] you could temporarily alter what the properties are returning during serialization. The events are actually designed to enable initialization and as such this solution is a bit of a hack. This solution is also not thread safe. But it does keep the code contained to the DataContract class and solves the problem quickly (and I think you are looking for quick).
Solution #2 mights look something like:
[DataContract]
public class TokenMessage
{
string tokenValue;
string extraValue;
bool enableExtraValue = true;
[DataMember]
public string Extra
{
get {
if (enableExtraValue)
return extraValue;
return null;
}
set { extraValue = value; }
}
[OnSerializing()]
internal void OnSerializingMethod(StreamingContext context)
{
enableExtraValue = false;
}
[OnSerialized()]
internal void OnSerializedMethod(StreamingContext context)
{
enableExtraValue = true;
}
}
Solution #2 is a quick fix (which is what I think you are looking for).
Solution #1 is the better design.

Try using IgnoreDataMemberAttribute

There is a approach, but I think this will require extra DataContract to be generated but still no need for separate operation and data contracts for different types of devices.
It can classic implementation to run-time polymorphism. I am just giving idea:
Say you have a generic DataContract like :
[DataContract]
[KnownType(typeof(Extra))]
[KnownType(typeof(Extra2))]
public class TokenMessage
{
string tokenValue;
string extraValue;
[DataMember]
public string Token
{
get { return tokenValue; }
set { tokenValue = value; }
}
}
Other device specific contracts can inherit TokenMessage as base class like:
[DataContract]
public class Extra:TokenMessage
{
[DataMember]
public string Extra
{
get ;set;
}
}
[DataContract]
public class Extra2:TokenMessage
{
[DataMember]
public string Extra2
{
get ;set;
}
}
Now at run-time as you say you know an argument in the operation contract, which helps us identify the device. Say based on device type, you can instantiate base class with derived class like:
TokenMessage tm= new Extra();
OR
TokenMessage tm= new Extra2();
So at run-time you will decide which device contract will be part of genric response.
Note: Adding KnownType will generate the separate xsd within wsdl for all known types within base class, but saves serialization for data at run-time as this should depend on actual inheritance chosen.

In your model add a property 'ShouldSerializeYOUR_PROPERTY_NAME', set it to false when you do not want the property serialized.
See more here: http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.shouldserializeproperty(v=vs.110).aspx

Related

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).

encapsulating method for list of objects

I have a class that looks like this:
public class MyModel{
public int TheId { get; set; }
public int ....
public string ....
}
I have another class that take a list of several types, including MyModel, and serializes the lists in json. It has several methods, one for each type of list.
public class ToJson{
public string MyModelToJson (List<MyModel> TheListOfMyModel) {
string ListOfMyModelInJson = "";
JavascriptSerializer TheSerializer = new ....
TheSerializer.RegisterConverters(....
ListOfMyModelInJson = TheSerializer.Serialize(TheListOfMyModel);
return ListOfMyModelInJson;
}
public string MyOtherModelToJson (List<MyOtherModel> TheListOfOtherModel) {....}
public string YetAnotherModelToJson (List<YetAnotherModelToJson> TheListOfYetAnotherModelToJson) {....}
}
What I want to do is encapsulate the serializing into MyModel, something like this:
public class MyModel{
public int TheId { get; set; }
public int ....
public string ....
public string MyModelToJson()
}
How can I encapsulate a method into an object so that it's available for a list of objects?
I thought of doing a foreach loop but that gets messy because in the calling method, you have to manipulate the json strings of each object in the list and concatenate them.
Let me know of OO principles of encapsulation apply in this case.
Thanks for your suggestions.
One way would be to define your ToJson as accepting a generic type:
public class ToJson<T>{
public string MyModelToJson (List<T> TheListOfMyModel) {
string ListOfMyModelInJson = "";
JavascriptSerializer TheSerializer = new ....
TheSerializer.RegisterConverters(....
ListOfMyModelInJson = TheSerializer.Serialize(TheListOfMyModel);
return ListOfMyModelInJson;
}
}
extension methods!
public static class JsonExtensions
{
public static string ToJson<T>(this List<T> list)
{
}
}
I'm not sure that I understand your question, but I think that what you want to do is not return a String but a JsonObject, JsonArray, or JsonPrimitive:
public class MyModel {
public JsonObject myModelToJson() ... //this method implements the interface!
}
Where JsonObject is a class that represents a json object.
Make this class implement an interface where the contract is that the return value is a JsonValue.
Then, in the ToJson class, return a JsonArray:
public class ToJson
public JsonArray myModelToJson(List<things that can be json-ized> myList) ...
}
Don't serialize the objects/arrays/primitives to a String until you absolutely need to, and let a library take care of the actual serialization.
That was a confusing answer.
Here's what I think you should do:
get hold of a decent json library. Ideally, it should have JsonObjects, JsonArrays, and JsonPrimitives which are subclasses of JsonElement. I've used Google gson in java, but I don't know what an equivalent C# version would be.
create an interface, JsonAble with one method -- toJson -- that returns a JsonElement.
implement this interface for all concerned classes
serializing a list of JsonAble objects is then very easy -- it becomes a JsonArray.
a decent json library should have a serialize method -- so you'll never have to worry about throwing strings around yourself
For what it's worth, I wouldn't remove the class at all. What you're talking about doing is adding an additional responsibility to your model, and apparently going against SRP heuristic. That is, you have a class whose current responsibility is to model data, and you're going to make it responsible for modeling data and also converting its data to some form, using various service classes that it now needs to know about. If the model class encapsulates GUI concepts like raising events for GUI, then it has divergent reasons to change - if the scheme for notifying the GUI changes and if the scheme for converting to JSON changes.
If it were me, I'd have the models inherit from a base class or define an interface as mentioned by Matt Fenwick, and have your ToJson class take a batch of those as input, process them, and return the result.
I understand the desire to eliminate the extra class, and might advocate it if it were a simple conversion involving only data elements of the class, but as soon as you need a service class of some kind to do the operation, it seems a poor fit for the model object, as you now cannot model data without a JavascriptSerializer. That's awkward if you want to model data that you don't then serialize.
One final thing that I can think of is that you can build on a'b'c'd'e'f'g'h's suggestion and piggy back the method onto some existing service, thus eliminating the class. If you just have a generic method on that service that implements the serialization, you can eliminate the separate class, since you no longer need a separate method for each model object type.

Metadata pattern for your object graph

I want to add metadata to my object graph for non-domain type data that will be associated to my objects but is not essential to the problem set of that domain. For example, I need to store sort settings for my objects so that the order in which they appear in the UI is configurable by the user. The sort indices should be serializable so that the objects remember their positions. That's just one among a few other metadata items I need to persist for my objects. My first thought is to solve this by having a MetadataItem and a MetadataItemCollection where the base Entity class will have a "Meta" property of type MetadataItemCollection. E.g.:
public class MetadataItem
{
public string Name;
public object Data;
}
public class MetadataItemCollection
{
/* All normal collection operations here. */
// Implementation-specific interesting ones ...
public object Get(string name);
public MetadataItem GetItem(string name);
// Strongly-type getters ...
public bool GetAsBool(string name);
public string GetAsString(string name);
// ... or could be typed via generics ...
public T Get<T>(string name);
}
public class Entity
{
public MetadataItemCollection Meta { get; }
}
A few concerns I can think of are:
Serialization - the database has a single table of EntityID | Name | Value where Value is a string and all types are serialized to a string?
Future Proofing - what if a metadata item's type (unlikely) or name needs to be changed?
Refactorability - should the keys come from a static list via enum or a class with static string properties, or should free-form strings be allowed:
var i = entity.Meta["SortIndex"];
vs.
public enum Metadatas { SortIndex };
var i = entity.Meta[Metadatas.SortIndex];
vs.
public static class Metadatas
{
public static string SortIndex = "SortIndex";
}
var i = entity.Meta[Metadatas.SortIndex];
Anything else?
Thoughts, ideas, gotchas???
Thanks for your time.
Solution:
Following #Mark's lead, and after watching the Udi video Mark linked to, I created two new interfaces: IUiPresentation and IUiPresentationDataPersistor. It's important to note that none of the objects in my Entity object model have any awareness of these interfaces; the interfaces are in a separate assembly and never referenced by my Entity object model. The magic is then done via IoC in the presentation models. It would be something like the following:
public class PhoneViewModel
{
IUiPresentationDataPersistor<Phone> _uiData
IUiPresentation<Phone> _presenter;
// Let IoC resolve the dependency via ctor injection.
public PhoneViewModel(Phone phone, IUiPresentationDataPersistor<Phone> uiData)
{
_uiData = uiData;
_presenter = uiData.Get(phone); // Does a simple lookup on the phone's ID.
}
public int SortIndex
{
get { return _presenter.SortIndex; }
set { _presenter.SortIndex = value; }
}
public void Save()
{
_uiData.Save();
}
}
It's a little more complicated in that the ViewModel implements INotifyPropertyChanged to get all the goodness that it provides, but this should convey the general idea.
Metadata literally means data about data, but what you seem to be asking for is a way to control and change behavior of your objects.
I think such a concern is much better addressed with a Role Interface - see e.g. Udi Dahan's talk about Making Roles Explicit. More specifically, the Strategy design pattern is used to define loosely coupled behavior. I'd look for a way to combine those two concepts.
As we already know from .NET, the use of static, weakly typed attributes severely limits our options for recomposing components, so I wouldn't go in that direction.

How to mark members that are required by runtime but shouldn't be used in code?

Sometimes the .NET runtime requires us to create public setters for properties which should really be read-only. For example:
XmlSerializer requires serialized properties to be writable, even if we only serialize one-way.
I have an unusual case in WPF where I need to have a TwoWay binding within a MultiBinding, even though conceptually the bound value will never change. This requires properties to be writable.
In each of these cases, I can leave the setter empty without affecting the functionality, but this is likely to lead to confusion down the line.
Given that I can't avoid having public setters on these properties, is there a way to generate compiler warnings when the setters are accessed? The attributes [Deprecated] and [Obsolete] would do the job, but the wording/intent isn't right.
The way I approach this problem is that I simply don't compromise the integrity my types for the purposes of serialization. The process of serialization is all about data and very little about behavior. I refuse to compromise the behavior of my types for a data only scenario.
Instead I design my types for the most efficient + safe usage. If the resulting type is not serializable and I find a scenario that requires it, I will create separate types which exist solely for the purpose of serializing my other types.
Here's a quick sample.
// My Core Immutable Type
namespace MyProject {
public sealed class Student {
private readonly string _name;
public string Name {
get { return _name; }
}
public Student(string name) {
_name = name;
}
}
}
// My Xml Serialization Type
namespace MyProject.Serialization {
public class SerializableStudent {
public string Name;
public SerializableStudent(Student source) {
Name = source.Name;
}
public Student ConvertToStudent() {
return new Student(Name);
}
}
}
For serialization, specifically, you can define the process manually by implementing the ISerializable interface.

Categories

Resources