I am building webservices for many different clients to connect to a database of automotive parts. This parts have a wide variety of properties. Different clients will need different subsets of properties to 'do their thing.'
All clients will need at least an ID, a part number, and a name. Some might need prices, some might need URL's to images, etc. etc. The next client might be written years from now and require yet a different subset of properties. I'd rather not send more than they need.
I have been building separate 'PartDTO's' with subsets of properties for each of these requirements, and serving them up as separate webservice methods to return the same list of parts but with different properties for each one. Rather than build this up for each client and come up with logical names for the DTO's and methods, I'd like a way for the client to specify what they want. I'm returning JSON, so I was thinking about the client passing me a JSON object listing the properties they want in the result-set:
ret = { ImageUrl: true, RetailPrice: true, ... }
First off, does this make sense?
Second, What I'd rather not lose here is the nice syntax to return an IEnumerable < DTO > and let the JSON tools serialize it. I could certainly build up a 'JSON' string and return that, but that seems pretty kludgey.
Suggestions? C# 'dynamic'?
This is a very good candidate for the Entity-Attribute-Value model. Basically you have a table of ID, Name, Value and you allow each customer/facet to store whatever they want... Then when they query you return their name-value pairs and let them use them as they please.
PROS: super flexible. Good for situations where a strong schema adds tons of complexity vs value. Single endpoint for multiple clients.
CONS: Generally disliked pattern, very hard to select from efficiently and also hard to index. However, if all you do is store and return collections of name-value, it should be fine.
I ended up going the dictionary-route. I defined a base class:
public abstract DictionaryAsDTO<T> : IReadOnlyDictionary<string, object>
{
protected DictionaryAsDTO(T t, string listOfProperties)
{
// Populate an internal dictionary with subset of t's props based on string
}
}
Then a DTO for Part like so:
public PartDTO : DictionaryAsDTO<Part>
{
public PartDTO(Part p, string listOfProperties) : base(p, listOfProperties) {}
// Override method to populate base's dictionary with Part properties based on
// listOfProperties
}
Then I wrote a JSON.NET converter for DictionaryAsDTO which emits JSON-y object-properties instead of key-value-pairs.
The web service builds an IEnumerable based on queries that return IEnumerable and serializes them.
Viola!
Related
I'm writing a C# application that does some things with baseball statistics. I'm getting the data from an XML web service. I want to completely separate the presentation-business-data layers. In that vain I have created a service class to interact with the web service and to create objects from the data, a set of business classes (i.e. player, team, league), and the objects needed for my presentation layer.
I don't want to load the statistics into the player class because there are more than 200 statistics, and I'm not going to need them every time I instantiate the player class. For each statistic I need its abbreviation, description, XML attribute name, and value.
Question: What C# data-structures or method could be used to present more than two properties and allow several of them to be static across all instances of the datatype and allow at least one to be writable at run-time?
I started to create a "statistic" class like this:
public class BaseballStatistic
{
public string Abbreviation;
public string Description;
public string XmlAttributeName;
public string Value;
public BaseballStatistic(string abbreviation, string description, string xmlAttributeName)
{
Abbreviation = abbreviation;
Description = description;
XmlAttributeName = xmlAttributeName;
}
}
The problem with this is that I'll never need to change the abbreviation, description, or XML attribute name at run-time.
If I only needed the abbreviation and value, I'd use a Dictionary or some other Key/Value pair.
I started to create a statistic class with abbreviation, description, XML attribute name, and value members. But the only one of those that will ever change at runtime is the value - so this didn't feel like the right answer. (Imagine 500 players, each with an array of statistic objects, and those object are the exact same for all players except for the value.)
I considered creating a multidimensional array, but with so many constant values, it seems wasteful to load such a thing at run time.
I feel like I should know this.
I should add this: because there are so many different statistics that I can use, it would be great if I could find a solution that would expose them to Intellisense. For example:
Statistic g = Stats.GamesPlayed
It sounds like you need one class for "a statistic" - and then a Dictionary<PlayerStat, int> (or whatever the value would be).
The PlayerStat class would know about the abbreviation, description and XML attribute name - and I'd suggest that you probably create a Dictionary<string, PlayerStat> statically to map from abbreviation to statistic, and another one to map from XML attribute to abbreviation.
You may not even need the Dictionary<PlayerStat, int> in your Player class... you could always add an indexer or method which looked things up lazily. (Be careful with this, however - you may find that loading many things lazily will be more expensive than loading everything in one go. You may want to break the statistics into categories, and load all the stats for a single category when you load one of them. Basically, if there are clumps of stats that are usually used together...)
I have been working on a client - server project. The server side implemented on PHP. The client implemented on C#. The websocket is used for connection between them.
So, here is the problem. Client will make a request. Json is in use for sending objects and validating against the schema. The request MUST HAVE it's name and MAY contain args. Args are like associative array (key => value).
Server will give a response. Response MAY contain args, objects, array of objects. For example, client sends a request like:
{
"name": "AuthenticationRequest",
"username": "root",
"password": "password",
"etc": "etc"
}
For this, server will reply with an AuthSuccess or AuthFailed response like:
{
"name": "AuthFailed",
"args": [
{
"reason": "Reason text"
}]
}
If response is AuthSuccess, client will send a requst of who is online. Server must send an array of users.
And so on. So the problem is, how to store those responses on a client side. I mean, the way of creating a new object for each response type is insane. They will be hundreds of request types, and each of them requires it's own response. And any changing in structure of request will be very very hard...
Need some kind of pattern or trick. I know it's kind of a noob way... But if anyone has a better idea of implementing request/response structure, please tell it.
Best regards!
I'd definitely go with a new class for each request type. Yes, you may need to write a lot of code but it'll be safer. The point (to me) is who will write this code?. Let's read this answer to the end (or directly jump to last suggested option).
In these examples I'll use Dictionary<string, string> for generic objects but you may/should use a proper class (which doesn't expose dictionary), arrays, generic enumerations or whatever you'll feel comfortable with.
1. (Almost) Strongly Typed Classes
Each request has its own strongly typed class, for example:
abstract class Request {
protected Request(string name) {
Name = name;
}
public string Name { get; private set; }
public Dictionary<string, string> Args { get; set; }
}
sealed class AuthenticationRequest : Request
{
public AuthenticationRequest() : base("AuthenticationRequest") {
}
public string UserName { get; set; }
public string Password { get; set; }
}
Note that you may switch to a full typed approach also dropping Dictionary for Args in favor of typed classes.
Pros
What you saw as a drawback (changes are harder) is IMO a big benefit. If you change anything server-side then your request will fail because properties won't match. No subtle bugs where fields are left uninitialized because of typos in strings.
It's strongly typed then your C# code is easier to maintain, you have compile-time checks (both for names and types).
Refactoring is easier because IDE can do it for you, no need to blind search and replace raw strings.
It's easy to implement complex types, your arguments aren't limited to plain string (it may not be an issue now but you may require it later).
Cons
You have more code to write at very beginning (however class hierarchy will also help you to spot out dependencies and similarities).
2. Mixed Approach
Common parameters (name and arguments) are typed but everything else is stored in a dictionary.
sealed class Request {
public string Name { get; set; }
public Dictionary<string, string> Args { get; set; }
public Dictionary<string, string> Properties { get; set; }
}
With a mixed approach you keep some benefits of typed classes but you don't have to define each request type.
Pros
It's faster to implement than a almost/full typed approach.
You have some degree of compile-time checks.
You can reuse all code (I'd suppose your Request class will be also reused for Response class and if you move your helper methods - such as GetInt32() - to a base class then you'll write code once).
Cons
It's unsafe, wrong types (for example you retrieve an integer from a string property) aren't detected until error actually occurs at run-time.
Changes won't break compilation: if you change property name then you have to manually search each place you used that property. Automatic refactoring won't work. This may cause bugs pretty hard to detect.
Your code will be polluted with string constants (yes, you may define const string fields) and casts.
It's hard to use complex types for your arguments and you're limited to string values (or types that can be easily serialized/converted to a plain string).
3. Dynamic
Dynamic objects let you define an object and access it properties/methods as a typed class but they will be actually dynamically resolved at run-time.
dynamic request = new ExpandoObject();
request.Name = "AuthenticationRequest";
request.UserName = "test";
Note that you may also have this easy to use syntax:
dynamic request = new {
Name = "AuthenticationRequest",
UserName = "test"
};
Pros
If you add a property to your schema you don't need to update your code if you don't use it.
It's little bit more safe than an untyped approach. For example if request is filled with:
request.UserName = "test";
If you wrongly write this:
Console.WriteLine(request.User);
You will have a run-time error and you still have some basic type checking/conversion.
Code is little bit more readable than completely untyped approach.
It's easy and possible to have complex types.
Cons
Even if code is little bit more readable than completely untyped approach you still can't use refactoring features of your IDE and you almost don't have compile-time checks.
If you change a property name or structure in your schema and you forget to update your code (somewhere) you will have an error only at run-time when it'll happen you use it.
4. Auto-generated Strongly Typed Classes
Last but best...so far we did forget an important thing: JSON has schema with which it can be validatd (see json-schema.org).
How it can be useful? Your fully typed classes can be generated from that schema, let's take a look to JSON schema to POCO. If you don't have/don't want to use a schema you still can generate classes from JSON examples: take a look to JSON C# Class Generator project.
Just create one example (or schema) for each request/response and use a custom code generator/build task to build C# classes from that, something like this (see also MSDN about custom build tools):
Cvent.SchemaToPoco.Console.exe -s %(FullPath) -o .\%(Filename).cs -n CsClient.Model
Pro
All the pros of above solutions.
Cons
Nothing I can think about...
Why is it a problem to create a class for each kind of Request / Response? If you have hundreds of different kinds of Requests and Responses, you might want to try and categorize them better.
I would argue there are common patterns across your requests or responses. Eg. a FailureResponse might always contain some status information and maybe an UserData-object (which could be anything depending on the use-case). This can be applied to other categories likewise (eg. SuccessResponse).
dynamic is a new static type that acts like a placeholder for a type not known until runtime. Once the dynamic object is declared, it is possible to call operations, get and set properties on it, even pass the dynamic instance pretty much as if it were any normal type. dynamic gives us a lot of rope to hang themselves with. When dealing with objects whose types can be known at compile time, you should avoid the dynamic keyword at all costs
You can read more about Dynamic
I'm proposing using AutoFixture and AutoFixture.xUnit at our company, and have gotten the mandate that for certain objects and fields they want random data that is formatted in an expected way. For example, they want PersonName to only populate with realistic names (instead of GUIDs) and PhoneNumber to only make strings that look like phone numbers. But they DON'T want to add data annotations to the actual objects enforcing this, they would just like the test data generated by AutoFixture to be pretty.
I've dealt a bit with ICustomize classes to implement greedy constructor behavior on a few classes. Is there a similar way to override the data generation for specific objects? To (for example) pull names from a list, or generate data to follow a certain regular expression? (keeping in mind that I can't actually add those regular expressions as attributes on the model)
Ok, solved my problem.
Object generation for a given class type can be accomplished via the Fixture.Register method. You can make a method that returns the type you want to override and that will be used instead of the default.
To get meaningful data I just used Faker.Net.
I got the solution Mark pointed out working, and really liked it for general POJOs, but in my case many of my objects had properties that could only be set via the constructor or aggregate setters (like ChangeContactInfo), so unfortunately I needed something a bit more targeted. Here is an example of my solution implementing a name and address generation override:
public class CustomObjectGeneration : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register(GenerateAddress);
fixture.Register(GeneratePersonName);
}
private Address GenerateAddress()
{
return new Address(Faker.Address.StreetAddress(), Faker.Address.SecondaryAddress(), Faker.Address.City(),
Faker.Address.ZipCode(), Faker.Address.UsState(), Faker.Address.Country());
}
private PersonName GeneratePersonName()
{
return new PersonName(Faker.Name.Prefix(), Faker.Name.First(), Faker.Name.First(), Faker.Name.Last(), Faker.Name.Suffix());
}
}
I'm currently trying to pick a C# ORM to use with my PostgreSQL database, and I'm interested in the micro-ORMs, since they allow me to better utilize the power of Postgres(and since full blown ORMs are hard to configure. While Dapper simply works, trying to deal with NHibernate has left a forehead shaped dent in my screen...)
Anyways, currently PetaPoco has the lead, but there is one feature I need and can't figure if it has(to be fair - I couldn't find it in the other ORMs either) - mapping of custom types.
My PostgreSQL database uses the hstore and Postgis extensions, which define custom types. I don't expect any ORM to support those types(it's hard enough to find one that supports PostgreSQL!) but I want to be able to provide my own mappers for them, so when I get them as columns or send them as parameters PetaPoco will automatically use my mappers.
Is this even possible? The closest I could find is IDbParameter support, but those are built-in types and I need to write mappers for extension types that are not part of the list...
Based on Schotime's comment, I came with half a solution - how to parse the hstore from the query results into the object. I'm leaving this question open in case someone wants to get the other solution.
I need to define my own mapper. Obviously I want to use PetaPoco's default mapping for regular types, so it's only natural to inherit PetaPoco.StandardMapper - but that won't work, because StandardMapper implements PetaPoco.IMapper's fields without the virtual attribute - so I can't override them(I can only overshadow them, but that's not really helping).
What I did instead was to implement IMapper directly, and delegate regular types to an instance of PetaPoco.IMapper:
public class MyMapper:PetaPoco.IMapper{
private PetaPoco.StandardMapper standardMapper=new PetaPoco.StandardMapper();
public PetaPoco.TableInfo GetTableInfo(Type pocoType){
return standardMapper.GetTableInfo(pocoType);
}
public PetaPoco.ColumnInfo GetColumnInfo(PropertyInfo pocoProperty){
return standardMapper.GetColumnInfo(pocoProperty);
}
public Func<object, object> GetFromDbConverter(PropertyInfo TargetProperty, Type SourceType){
if(TargetProperty.PropertyType==typeof(HStore)){
return (x)=>HStore.Create((string)x);
}
return standardMapper.GetFromDbConverter(TargetProperty,SourceType);
}
public Func<object, object> GetToDbConverter(PropertyInfo SourceProperty){
if(SourceProperty.PropertyType==typeof(HStore)){
return (x)=>((HStore)x).ToSqlString();
}
return standardMapper.GetToDbConverter(SourceProperty);
}
}
The HStore object is constructed similarly to the one in Schotime's gist.
I also need to register the mapper:
PetaPoco.Mappers.Register(Assembly.GetAssembly(typeof(MainClass)),new MyMapper());
PetaPoco.Mappers.Register(typeof(HStore),new MyMapper());
Now, all of this works perfectly when I read from the query - but not when I write query parameters(even though I defined GetToDbConverter. It seems my mapper simply isn't called when I'm writing query parameters. Any idea how to do that?
I have a function that identify coordinates on a page, and I am returning them as a
Dictionary<int, Collection<Rectangle>> GetDocumentCoordinates(int DocumentId)
However, later I need information about each page - if it was validated, what is the page resolution, color/bw, etc. I could create another function and run through pretty much the same result set as the previous function and get that information.
Dictionary<int, PageInfo> GetDocumentAttributes(int DocumentId)
Another alternative would be to add a ref parameter so I can get these values back.
Dictionary<int, Collection<Rectangle>> GetCoordinates(int DocumentId, ref Dictionary<int, PageInfo> PageAttributes)
Yet another alternative is to create an encompassing class that contains the Dictionary and the page information:
class DocumentInfo
{
Dictionary<int, Collection<Rectangle>> Coordinates { get; set;}
Dictionary<int, PageInfo> PageAttributes { get; set; }
}
and then define:
DocumentInfo GetDocumentInfo(int DocumentId);
I'm leaning towards the last option, but your insights are very much appreciated.
The last option is definitely the best. I've found that, when taking or returning complex data with multiple meanings, creating a complex type to encapsulate this data is the best practice for a number of reasons.
First, your return data probably will change as your design changes. Encapsulating this data in an object allows you to alter what it carries and how your methods operate on this data without altering the interfaces of your objects. Obviously, your data object shouldn't implement an interface; at most, have a base class with the minimum interface and then pass references to the base around.
Second, you may find your data gets complex to the point where you will need to perform validation on it. Rather than have this validation in all the methods of your classes where you act upon this data, you can easily wrap this up in the data class. Single responsibility, etc.
It seems like you need a lot of data out. The last option should be fine, and is extensible; it you wanted (to simplify the Dictionary<,> usage), you could encapsulate things a bit more, but the fact that C# doesn't directly support named indexed properties means you'd need a few classes, unless you just wrap with methods like:
class DocumentInfo {
Dictionary<int, Collection<Rectangle>> rectangles = ...
public Collection<Rectangle> GetRectangles(int index) {
return rectangles[index]; // might want to clone to
// protect against mutation
}
Dictionary<int, PageInfo> pages = ...
public PageInfo GetPageInfo(int index) {
return pages[index];
}
}
I'm not quite clear what the int is, so I can't say whether this is sensible (so I've just left it alone).
Also - with the first option, you probably wouldn't need ref - it would be sufficient to use out.