Reputation: 25221
I have an interface to a .NET service layer, which, in turn, will communicate with a third-party system via a web service. This handles a number of different tasks related to the third-party system's functionality (it is actually a bespoke CRM system, but as the context isn't relevant I will swap this out for something trivial).
The interface looks something like this:
public interface IMyService
{
CarModel GetCar(string registration);
CarModel AddCar(Car car);
PersonModel GetPerson(string personId);
PersonModel AddPerson(Person person);
}
Now, my models currently work as follows: I have a BaseResponseModel
, from which each SomethingModel
inherits. Each SomethingModel
contains some basic properties and also wraps a Something
- like so:
Base response model
public class BaseResponseModel
{
public List<string> Errors { get; set; }
public bool HasErrors
{
get
{
return (Errors != null && Errors.Count > 0);
}
}
}
Specific response models
public class CarModel : BaseResponseModel
{
public Car Car { get; set; }
}
public class PersonModel : BaseResponseModel
{
public Person Person { get; set; }
}
Here, Car
and Person
simply contain a bunch of public properties. Then, each method of my IMyService
takes its arguments, formats a request to an .asmx web service, parses the response into its response model and returns it to the caller (an .ascx codebehind).
However, the number of different ...Model
classes (not to mention that they all have different property names for their wrapped objects) is becoming ugly. I am of a mind to do something along the lines of the following:
public class Car
{
public string Registration { get; set; }
}
public class ServiceResponse<T>
{
public List<string> Errors { get; set; }
public bool HasErrors { ... }
public T Result { get; set; }
}
public interface IMyService
{
ServiceResponse<Car> GetCar(string registration);
ServiceResponse<Car> AddCar(Car car);
ServiceResponse<Person> GetPerson(string id);
ServiceResponse<Person> AddPerson(Person person);
}
My ASP.NET controls will then receive ServiceResponse<T>
from every method in IMyService
.
Is this the "conventionally correct" usage of generics in C#? Or is this simply masking deeper architectural flaws with my solution? Is there something missing from my proposed solution (though note that the implementations of the different Get
and Add
methods aren't as generic as the prototypes make them seem)?
Disclaimer: Apologies if this question is "too subjective," but it seemed too specific to be a theoretical question for Programmers.SE and a little too generic to be a question for CodeReview.SE. I am open to suggestions on how to improve the question if necessary.
Upvotes: 8
Views: 527
Reputation: 1736
Probably my answer is too subjected as well - but I'd suggest avoiding creation of dependencies before you have a stable working system at least in beta version. Especially when you're at the beginning of development. Also as inheritance in one of the strongest relation types, it should be put aside as long as possible.
Adding base class or generic, which looks the same, you put yourself into a very tough frames.
What if, say, there is a situation where you come up with dictionary or errors? Or you'd need special response code to CarRequest? Or special response type like 'redirect'?
So - my suggestion is that you make a special kind of response per request until you find out some response similarities after significant amount of development.
There should be GetCarResponse
to GetCar
. Are you planning errors in response? Just throw an exception. Not found? Return null. Found? Return what you found and do not bother with errors.
Probably that requires a little more coding, but you have your hands free off some artificial limitations.
Upvotes: 0
Reputation: 48486
I don't see a problem with this use of generics, unless you would have someone using your service from something other than .NET perhaps. I think it generates quite ugly contract names for the WSDL.
So for your use case, I'd say it's fine. I'm glad you changed from Model
to Response
as well. I was going to suggest that.
Depending on how the errors are used, I would personally prefer to raise an (aggregated) exception for them. However, if you use it for forms validation or something, I would say that's acceptable.
Upvotes: 2