We want to send two collections of objects out of a WCF service. The classes for the two objects share some common properties, and each have others, unique to them...
public class TypeA {
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
public string D { get; set; }
}
public class TypeB {
public string A { get; set; }
public string B { get; set; }
public string E { get; set; }
public string F { get; set; }
}
Yes I could/should use a common base class, but that isn't the question here
One the one hand, having two classes like this means that each class only has the properties it needs, which keeps it slim and focused. On the other hand, as these are basically two different views of the same underlying object, it's perfectly reasonable to combine them, and just populate the properties needed.
I can't find a way of seeing how big the WCF payload is, so don't know if using one common class is going to consume more bandwidth than using specific classes. I need this to be as efficient as possible.
Anyone know if using one common class is going to increase the WCF payload? If so, any way of find out how much?
You can put the XmlSerializerFormat attribute on your services in order to force WCF to use ASP.NET serialization engine when sending your objects. This will allow you to use other attributes and methods to take full control over which properties are serialized.
Then, you can restrict properties from being serialized using two methods:
1. Implement a ShouldSerializeXXXX() method
2. Use the DefaultValue attribute. Properties which already have the default value are not serialized.
Example:
[XmlSerializerFormat, ServiceContract]
public interface IMyService
{
[OperationContract]
MyData GetData();
}
[DataContract]
public class MyData
{
[XmlAttribute, DataMember]
public int Value1 { get; set; }
// Explicit method to control serialization of Value1 property
public bool ShouldSerializeValue1()
{
// do not serialize this value if it's 0
return Value1 != 0;
}
// Use default value of 0 to prevent serializing zeros
[XmlAttribute, DataMember, DefaultValue(0)]
public int Value2 { get; set; }
}
I would be more concerned with the data transfer type you are using if you are worried about packet size. For example, if you are using the SOAP protocol, then your packet size is going to be very large and instead of worrying about base classes to objects, you could shrink down your packet size tremendously by switching to binary, or even JSON. See here for reference: https://dzone.com/articles/wcf-rest-xml-json-or-both
Also, to inspect true packet size I would install 'fiddler' on your machine and inspect the data as it goes over the network.
I hope that sets you on the correct path...
Related
I'm deserializing some JSON responses and putting them into one of two primary classes depending on if a single object is returned or if a list of objects is returned. I'm currently using
public class MultiResponse
{
public List<DeserializedResult> Result { get; set; }
}
public class SingleResponse
{
public DeserializedResult Result { get; set; }
}
public class DeserializedResult
{
public string Id { get; set; }
public string AccountName { get; set; }
}
to contain the response(s). However I know it's not the best way, especially since I'm having to use a dynamic return in the calling class to deal with the two types of responses possible. I think an abstract class (or interface?) is a better way to do this, but I don't know how to implement it. Am I on the right track & if so, how do I construct the abstract class and do the inheritance?
Create a design based on multi responses - i.e. holding / returning a list even if when there is only one object. It eliminates the design "hint" that there is a special case somehow. And The resulting code will be more consistent and robust.
The focus should be on the object itself - what you do with it after re-hydration. Not on the trivial happenstance that I have one object or more than one. That distinction is no different that "4 objects or not 4 objects."
Abstracting the container to a single class necessarily makes working with the objects the focus, the emphasis of your design.
edit
Think of it this way. Single or multiple deserialized objects is a consequence of how many objects there were to deserialize. It is an implementation detail not germane to the (deserialized) objects actual use. Encapsulate implementation details, that is, hide them from the client code. Give clients classes and methods that express functionality in "business domain" terms.
end edit
Edit
... I'm having to use a dynamic return in the calling class to deal with the two types of responses possible. I think an abstract class (or interface?) is a better way to do this, but I don't know how to implement it.
Main points:
ClientApi transforms the deserialized object to the desired class.
Two API's!
constructors called by the de-hydrating object
Hide the default constructor to ensure valid object instantiation
GetDeHydratedJsonThingy called by the "using" client.
Deserializer and "using" client are decoupled thanks to the ClientApi class.
De-hydration works with DeserializedResults objects
"Using" client only cares about MultipleResponse objects
"using" client deals with only one return type.
P.S. After I wrote this I realized only one "Response" class is needed, now that ClientApi class encapsulates the object instantiations. Commented out code is original.
P.P.S. My method and parameter names are really lousy. Use names that have meaning in the problem domain. i.e. user's terminology.
.
public class ClientApi {
protected MultiResponse MoreThanOne { get; set; }
// protected SingleResponse OnlyOne { get; set; }
protected ClientApi ( );
public ClientApi (List<DeserializedResult> theList) {
if (theList == null) throw ArgumentNullException("error message here");
// add overloaded constructors to MultiResponse class.
MoreThanOne = new MultiResponse (theList);
// OnlyOne = null;
}
public ClientApi (DeserializedResult onlyOne)
if (onlyOne == null) throw ArgumentNullException("error message here");
MoreThanOne = new MultiResponse(onlyOne);
// OnlyOne = onlyOne;
}
///<summary>
/// Always returns an object. The list may be empty,
/// but never null
///</summary>
public MultiResponse GetDeHydratedJsonThingy() {
MultiResponse HereYaGo = new MultiResponse();
// if (MoreThanOne !=null) HereYaGo.AddRange(MoreThanOne);
// if (OnlyOne != null) HereYaGo.Add(OnlyOne);
HereYaGo.AddRange(MoreThanOne.Result);
return HereYaGo;
}
}
end Edit
You can try the following with a generic base abstract class
public abstract class Response<T> {
public T Result { get; set; }
}
The concrete implementations would inherit from the common base response.
public class Response : Response<object> {
public object Result { get; set; }
}
public class MultiResponse : Response<List<DeserializedResult>> {
public List<DeserializedResult> Result { get; set; }
}
public class SingleResponse : Response<DeserializedResult> {
public DeserializedResult Result { get; set; }
}
I am trying to work out the best way to approach the following ..
i need to pass AvailabilityOption/LimitedAvailabilityOption types to - well a service as it happens, and then get back BookingOption types.
I have routines which will generate the availability types, but am unsure if i need to go through each of my Option objects effectively duplicating versions of them inheriting from BookingOption and AvailabilityOption in turn. or can I do some sort of 'Decoration' of the simple options with the availability classes and then cast them back down to booking ones when i pass them back again.
I know there is a decoration pattern but having read a bit about this it appears that it is more about decorating at runtime.. I may well be misunderstanding.
I suspect I havent explained this very well but here is some code..
EDIT: effectively the option is a base for a number of possible options on a booking - such as an excursion or some other extra, of which there are quite afew. the availability extends that to determine what space there is on any option, but it is just extending the option itself, with the price and possibly the numbers already booked on that option.
the BookingOption is there to be returned from the routine that effectively chooses from the options based on their price and availability. I am just trying to return the bare minimum at the booking point, which is really the date when the option is required and which option it is. the availability at this point is moot..
public abstract class Option{
public int OptionID { get; set; }
public OptionType OptionType { get; set; }
public string EqtCode { get; set; }
public string CentreCode { get; set; }
public virtual string Description { get; set; }
}
public abstract BookingOption : Option{
public DateTime WeekStartDate{get;set;}
}
public abstract class AvailabilityOption : BookingOption {
public decimal Price{get;set;}
public override string Description{
get{return string.format("{0} # {1}", base.Description, Price.ToString());
set{ base.Description = value;}
}
}
public abstract class LimitedAvailabilityOption : AvailabilityOption{
public int MinNumber { get; set; }
public int MaxNumber { get; set; }
public int TotalBooked { get; set; }
public int TotalRemaining { get; set; }
public override string Description
{
get
{
return string.Format("{0} ({1} # {2})",
base.Description, TotalRemaining.ToString(), Price.ToString());
}
set { base.Description = value;}
}
}
public class Option1 : Option{
public Option1(){}
}
public class Option2 : Option{
public Option2(){}
}
public List<BookingOption> BookWithAvail(List<AvailabiliyOption> options){
//pick options based on avail and pass back the booking versions so write away...
}
It looks like answer depends on how you plan to use Availability and Limited availabilitty qualities of essences. If those availability-qualities are only applicable to LimitedAvailabilityOption and AvailabilityOption classes - than it does not seems there is a big need of implementation Availability or LimitedAvailability in separate classes, as each of those classes will be used to distinguish only one kind of other essences (LimitedAvailabilityOption and AvailabilityOption respectively). It would make sense to use decoration pattern and implement classes for Availability and Limited availability qualities only if you plan assign each of them to multiple essences that are not connected with inheritance relationship (including inheritance through intermediate classes). And if you plan to spread usage of availability-qualities across multiple classes that are not supposed to have any inheritance connection via common ancestor that has availability property - then the only choice is to extract those availability qualities into separate classes.
I have a group of POCO classes:
class ReportBase
{
public string Name { get; set; }
public int CustomerID { get; set; }
}
class PurchaseReport : ReportBase
{
public int NumberOfPurchases { get; set; }
public double TotalPurchases { get; set; }
public bool IsVip { get; set; }
}
class SaleReport : ReportBase
{
public int NumberOfSales { get; set; }
public double TotalSales { get; set; }
}
I have a web method to return ReportBase. The caller uses the return value to update UI(WPF) based on the actually type by downcasting and checking the type (one grid for sale and one for purchase). Someone suggested to use three web methods and each return the specific type.
I understand that downcast is in general against design principle by introducing if/else. Instead we should use virtual functions. But in POCO class, we don't really have virtual behaviors (only extra fields).
Are you for or against downcast in this case, why?
IMO it's all about intention. Returning just the base class doesn't say anything, especially as you return it only to save some key strokes. As a developer what do you prefer?
ReportBase GetReport() // if type==x downcast.
//or
PurchaseReport GetPurchaseReport()
SaleReport GetSalesReport()
What approach would you want to use to make the code more maintainable? Checking type and downcasting is an implementation detail after all and you probably have a method like this
public void AssignReport(ReportBase report)
{
//check, cast and dispatch to the suitable UI
}
What's wrong with this? It's lacking transparency, and this method should always know about what reports are needed by what UI elements. Any time you add/remove an element you have to modify this method too.
I think is much clear and maintainable something like this
salesGrid.DataSource=repository.GetSalesReport();
purchaseGrid.DataSource=repository.GetPurchaseReport();
than this
var report=repository.GetReport();
AssignReport(report); //all UI elements have their data assigned here or only 2 grids?
So I think that, POCO or not, I will favour the three web methods approach.
I want to specify that one property in an XML serializable class is an attribute of another property in the class, not of the class itself. Is this possible without creating additional classes?
For example, if I have the following C# class
class Alerts
{
[XmlElement("AlertOne")]
public int AlertOneParameter { get; set; }
public bool IsAlertOneEnabled { get; set; }
}
how can I specify that IsAlertOneEnabled is an attribute of AlertOne so that the XML serializes to the following?
<Alerts>
<AlertOne Enabled="True">99</AlertOne>
</Alerts>
If you are using XmlSerializer with default (non-IXmlSerializable) serialization, then indeed: this cannot be achieved without adding an extra class that is the AlertOne, with an attribute and a [XmlText] value.
If you implement IXmlSerializable it should be possible, but that is not a nice interface to implement robustly (the deserialization, in particular, is hard; if it is write-only then this should be fine). Personally I'd recommend mapping to a DTO model with the aforementioned extra class.
Other tools like LINQ-to-XML would make it pretty simple, of course, but work differently.
An example of a suitable DTO layout:
public class Alerts
{
[XmlElement("AlertOne")]
public Alert AlertOne { get; set; }
}
public class Alert
{
[XmlText]
public int Parameter { get; set; }
[XmlAttribute("Enabled")]
public bool Enabled { get; set; }
}
You could of course add a few [XmlIgnore] pass-thru members that talk to the inner instance.
We have a huge client/server WinForms app that uses .NET remoting to pass DAOs between the layers, which has a few problems.
All of the DAOs were defined to use fields instead of properties long before I got here, and you can't bind fields to controls.
Adding fields or properties to a DAO changes the serialization format, requiring a dual client/server deployment, which is much more difficult for us than either a client or server deployment (we have to work around doctors' schedules to minimize downtime).
Using a simple, contrived, and imaginary example, would changing the object from this:
public class Employee
{
public int ID;
public string Name;
public DateTime DateOfBirth;
}
to this:
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
change the serialization format, breaking compatibility with older clients?
Important edit: this should be compatible and allow binding?
public class Employee
{
private int id;
private string name;
private DateTime dateOfBirth;
public int ID { get {return id;} set {id = value;} }
public string Name { get {return name;} set {name = value;} }
public DateTime DateOfBirth { get {return dateOfBirth;}
set {dateOfBirth = value;} }
}
Certainly worth a try, no?
Yes, this will cause problems if client/server are out of sync.
.NET remoting uses BinaryFormatterm which (without a bespoke ISerializable implementation) uses the field names. Using automatic properties breaks the field names.
As long as you update client and server at the same time, it should work. Another option is to use name-independent serialization, such as protobuf-net. I can provide an example if you want (it supports ISerializable usage).
(by the way, adding properties should not affect BinaryFormatter, since it is field-based)
As requested, here's an example of using protobuf-net to control remoting serialization (taken directly from one of my unit tests); note that this will also be incompatible until both client and server agree, but should withstand changes after that (it is designed to be very extensible). Note that there are lots of ways of using it - either explicit member notation (like data-contracts) or implicit fields (like BinaryFormatter), etc (everything in between)... this is just one way of using it:
[Serializable, ProtoContract]
public sealed class ProtoFragment : ISerializable
{
[ProtoMember(1, DataFormat=DataFormat.TwosComplement)]
public int Foo { get; set; }
[ProtoMember(2)]
public float Bar { get; set; }
public ProtoFragment() { }
private ProtoFragment(
SerializationInfo info, StreamingContext context)
{
Serializer.Merge(info, this);
}
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context)
{
Serializer.Serialize(info, this);
}
}
Here, the bottom 2 methods satisfy ISerializable, and simply pass execution to the protobuf-net engine. The [ProtoMember(...)] defines fields (with unique identification markers). As already stated, it can also infer these, but it is safer (less brittle) to be explicit.