I have a WCF service which exposes its interface with DTOs. I have an entity class MyClass which has two properties SimpleProperty1 and SimpleProperty2. There is a calculated property in this class named CalculatedProperty1 which uses the above two properties in calculating its value. I have a MyClassDTO dto class which has only the two simple properties.
In the UI, where a MyClassDTO object is being modified, I want the user to see the value of CalculatedProperty on the fly. However, as according to my understanding DTOs should not have any logic embedded in them. And it seems a bit of a waste to implement a function in the web service to get the calculated value of the property in such a simple scenario. How should I go about getting this done? What are the standard approaches of doing this? I see that the generated classes from the WCF service are defined as partial classes. Is it there to handle this sort of scenario?
you can use extension method to show the calculated property
public class MyClassDTO
{
public string P1 { get; set; }
public string P2 { get; set; }
}
public static class MyClassDtoExtension
{
public static string ToCalculatedProperty(this MyClassDTO obj)
{
return obj.P1 + obj.P2;
}
}
// usage
var d = new MyClassDTO(){P1 = "1",P2 = "2"};
d.ToCalculatedProperty();
Related
I am curently working on a small project (C#) where I have data to analyse.
To do so, I pass the data into the constructor of a class.
The class makes a first analysis on the data, and a certain value is determined using the data. Using this value I can say that this data is of Type B, C, D, ... and the analysis would continue in another class corresponding to the data type.
This would be it's class diagram representation :
So the "Data" Class should abstract but not really ? ¯\_(ツ)_/¯
I did some reasearch about the factory design pattern, but I think this is not really what I am trying to achieve. Is there maybe an other design pattern that does what I want to do?
Thank you for helping.
If I understand you correctly, you want the base class to determine which child class to create based on the data passed into the constructor. If so, you can't do it that way - a class cannot change itself to be a different/derived type when being constructed.
I assume that all the data types have some common properties and so you decided to put those common properties in a base class. I also assume you don't want each data type child class to have redundant code setting those common properties in the base class. You accomplish that by having the child class call a method in the base class, passing the data. You can do this in the constructors if you wish. For example:
class BaseData
{
BaseData(Dictionary<string,string> data)
{
this.CommonProp1 = data["CommonProp1"];
this.CommonProp2 = data["CommonProp2"];
}
public string CommonProp1 { get; set; }
public string CommonProp2 { get; set; }
}
class DataTypeA : BaseData
{
DataTypeA(Dictionary<string,string> data)
: base(data) // <-- magic here
{
this.TypeA_Prop1 = data["TypeA_Prop1"];
this.TypeA_Prop2 = data["TypeA_Prop2"];
}
public string TypeA_Prop1 { get; set; }
public string TypeA_Prop2 { get; set; }
}
I believe the factory pattern actually is what you want since you want to create an instance of a class in which the type is determined at run time. This is where you encapsulate the code that determines which type of child class to create. Something like:
class DataFactory
{
public static BaseData BuildDataClass(byte[] serializedData)
{
Dictionary<string,string> data = ParseData(serializedData);
switch (data["DataType"])
{
case "TypeA":
return new DataTypeA(data);
default:
return null;
}
}
private static Dictionary<string,string> ParseData(byte[] serializedData)
{
var data = new Dictionary<string, string>();
// bla bla
return data;
}
}
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; }
}
This is kind of a design problem:
class Suite
{
List<Plugins> Plugins {get;set;}
}
class DataCollector : Plugin
{
string Property1 {get;set;}
string Property2 {get;set;}
public void PrintMyName();
}
class Measurement: Plugin
{
string Property1 {get;set;}
string Property2 {get;set;}
public void PrintMyName();
}
Now, I want the class suite to be serializable. The problem here is this:
XMl serialization is basically used to serialize DTO kind of objects so you basically serialize/deserialize your stateful properties and that is fine
This particular class which is going to serialized contains of Type Plugin(which contains combination of properties which contains some property values) + functionalists.
Which means I need to use factory to get the real instance of the object for Plugin to come to life with all its functionality with the property values.
Am I looking at an XMLSrializable + Factory combination? Is there any good elegant way to achieve this?
Why not implement the IDeserializationCallback interface so upon deserialization you can bring your object back to life via a call to your factory.
I don't really understand the purpose of your classes, but I will give an example as best I can:
public class MyDataClass : IDeserializationCallback
{
public int SimpleKeyProperty { get; set; }
public string TextProperty{ get; set; }
public void OnDeserialization(object sender)
{
//upon deserialization use the int key to get the latest value from
//factory (this is make believe...)
TextProperty = SomeFactory.GetCurrentValue( this.SimpleKeyProperty) ;
}
}
In my domain model I have an Entity object that looks as follows:
public class Group
{
public int idGroup { get; set; }
public string Description { get; set; }
}
I have a repository for this object:
public class GroupRepository : IGroupRepository
{
public Group LoadGroup(int idGroup)
{
//imitation of SQL data reader
Group g = new Group();
g.idGroup = Convert.ToInt32(r["idTipoGrupo"]);
g.Description = Convert.ToString(r["Descricao"]);
return g;
}
}
But now I need to get some extra information from data store about Group objects through a new function in my created repository, here are the fields I need:
public bool HasChildGroups { get; set; }
public int ChildGroupsCount { get; set; }
public bool HasDeals { get; set; }
public int DealsCount { get; set; }
These properties look to me like a "service" or "helper" properties and I don't plan to use them everywhere in my application, only few times, but I need them. The simplest thing I could think of is that I added these "service" properties to my Group object and created a method in my repository that populates them. But I consider doing this wrong, as it is the Entity and I don't need them in here. So where should I keep such "service" objects? Do I have to create a new class that inherits from Group like this:
public class GroupHelper : Group
{
public bool HasChildGroups { get; set; }
public int ChildGroupsCount { get; set; }
public bool HasDeals { get; set; }
public int DealsCount { get; set; }
}
Or should I consider using some Data Transfer Objects?
How would you solve this problem?
Any help appreciated.
The first question to ask is how the state of the proposed GroupHelper object is managed. Attributes such as HasChildGroups seems like they would be altered as a result of behaviors invoked on a Group entity. If so, then they should be first class entities in your domain model, perhaps event part of the group entity itself. If the properties are managed outside of your domain model then you can just query that data as you would any other external data source. I would have this be a standalone object, perhaps called something like GroupInfo not extending Group itself.
What seems to be the issue here is that you have query requirements that aren't in alignment with the shape of your entities. In that case you have the flexibility to decouple your read-models from your domain models. Read-models are intended to fulfill query requirements and your domain models are intended to host behavior associated with your domain.
HasChildGroups [...] look to me like a "service" or "helper" properties [...] But I consider doing this wrong, as it is the Entity and I don't need them in here.
If you concider your Group object to be a data access object and you have a separate model for, say, viewdata, you're right.
But this may also be a fat class, providing in view-specific and database-specific code. It's not plain wrong.
You could indeed create a GroupDTO class that provides the properties you require in the application but not for the data access, to separate concerns.
I have a WinForms application that creates a huge, custom textfile. To do this requires the user to configure dozens of controls on the main form and then click a Submit button. What is the best way to pass all those control values to my Generator class? The problem is I'm ending up with 20+ parameters to pass to a Generate() method. I can group some of those into Config objects (i.e. the date/time controls can be passed into a DateTimeConfig object) and then pass these config objects into the Generate() method to minimize the number of parameters needed, but it still feels like there must be a better way. Any ideas?
EDIT: Thank you for your responses, but I was hoping for something other than a configuration object (as that's what my OP mentioned). I guess what I was hoping for is some way to serialize the values of all the controls automatically, without having to build a custom object and then modify that everytime a control changes or gets added/removed.
Why not create a custom object class as container of your data and then pass the istance of this class to the Generator method as parameter?
Look into Model Driven Development, where the parameters are grouped into business objects or data transfer objects (DTOs). This is a more intuitive way to group parameters than by datetime, etc.
If you place those model objects in a separate project, you can pass those objects around the solution (from one method to another and one project to another) without having to serialize them or mess with long parameter list ordering. You can even nest model objects inside other model objects.
In this example, notice you only have to change parameters in the Person object or the Address object and you never have to serialize or map anything:
// this is my business model object
public class Person
{
public int PersonId { get; set; }
public string PersonName { get; set; }
// notice the Address object nested in the Person class
public Address HomeAddress { get; set; }
}
// this is another class that lives inside the person class
public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
In one class you could have this method that receives a person with an address and passes the person to another class's SavePerson class:
public void ProcessPerson(Person person)
{
person.PersonName = "Robert";
Address address = new Address();
address.City = "Austin";
person.Address = address;
SavePerson(person);
}
Some other class (even in another project) can take that person and pass it to the persistence layer:
public void SavePerson(Person person)
{
database.Save(person);
}
So if I want to add a State to the person I just change the Address class and I'm all done in one step, I don't have to add the state field to all the method parameter lists:
public class Address
{
public string Street { get; set; }
public string City { get; set; }
// this is the new property
public string State { get; set; }
}
Create a model object that has a value for each control.
So let's say you have a form that has a first name, last name, birthday and salary.
Your model would be
public class SalaryModel
{
public string FirstName {get; set;}
public string LastName {get; set;}
public DateTime Birthday {get; set;}
public decimal Salary {get; set;}
}
Then when submit is clicked, you create this object and pass it to your generator class.
One reason for this is your generator needs to know NOTHING about the control other than it's value. That is a generator class shouldn't be concerned about .IsVisible() or .TabOrder or any of that other junk. It only cares about what the value is.
Create a container class. Keep an instance of it common for your main form and whatever form is going to use it/pass it to the other form or class as parameter.
Take all the values from your form and fill the container class. Usually a container/entity class would be full of properties and will have a very few methods.
Move you Generate() Method to a class and utilize the class properties. You can also then support data binding from you form.
Ex.
Take this
Generate (List<int> x, bool Opt1);
to This
public class Generate
{
List<int> Ids {get;set;}
bool Opt1 {get;set;}
bool Generate();
}