How to handle multiple identical classes in C#

  • A+

I'm working with a client's API that has multiple different 'services' (around 10 so far), each one imports as its own namespace. Part of their standard API call pattern involves returning an array of error messages:

public class Error {     public String ErrorMessage {get;set}     public int errorNumber {get;set}     ..etc } 

I've been trying to clean up and unify our handling of those messages. I tried to make a single function to handle them, eg:

void CheckErrors(List<Error> errors) {     if(errors != null && errors.Count() > 0)          throw new Exception(errors.First().ErrorMessage); } 

(the actual function is more complex but that gives the general idea)

However, it turns out that every one of their services has its own (identical) definition of this Error class. In C++ I could just template this function and it would work fine, or in a dynamic language it'd just work, but in C# I haven't been able to find a way to do this without making 10+ copies of the same function, each with a different namespace on the Error type.

In my own code I could just add an interface to these classes, but since it's not my code I don't think you can do that in C#? I could make a wrapper class that inherits from each of these and implements the interface, but I'm still stuck with duplicate code for every namespace/service.

Is there any cleaner way to handle this?

Bear with me... you may need yet another Error class that is identical in properties to their Error class, but that you define in your namespace.

Your method CheckErrors uses your definition of Error.

Finally, you can use AutoMapper to map between their Error types and yours. This is pretty much exactly what AutoMapper is designed for. Since all your contracts are identical, the AutoMapper configuration should be trivial. Of course, you incur some runtime expense of mapping, but I think this would lead to the cleanest statically typed solution given that you can't change their interfaces.

The AutoMapper config + usage will look something like this:

//See AutoMapper docs for where to put config, it shouldn't happen on every call var config = new MapperConfiguration(cfg =>  {     cfg.CreateMap<TheirApi.Error, MyNamespace.MyErrorDefinition>(); } var mapper = config.CreateMapper();  MyErrorDefinition myErrors = mapper.Map<List<MyErrorDefinition>>(listOfTheirErrorObjects); CheckErrors(myErrors); 


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: