Reputation: 6579
I need to return object values when I call methods. However, I also need to pass error messages along with these methods. As such I came up with an object like this:
public class ReturnObject
{
public bool Success { get; set; }
public IEnumerable<string> Errors { get; set; }
public dynamic Result { get; set; }
}
Now from my services, I can call this and return whatever I want along with any errors. However, the problem is that this is not type safe and I need cast the Result every time. So my goal is to make it type safe. Here is how I came up with that:
public class ReturnObject<T>
{
public bool Success { get; set; }
public IEnumerable<string> Errors { get; set; }
public T Result { get; set; }
}
Now, I return this object a lot, and as such, I Created a service which will return me the object. Trying to keep my code a bit dry. The service looks like this:
public class ResultService<T>
{
public ReturnObject<T> GetGoodResult(T result)
{
return new ReturnObject { Success = true, Result = result };
}
public ReturnObject<T> GetGoodResult(T result, IEnumerable<string> errors)
{
return new ReturnObject { Success = false, Errors = errors, Result = result };
}
}
So now lets says I have a service I want to use this from.
public class BookService
{
private ResultService<book> _resultServiceBook = new ResultService<Book>();
private ResultService<string> _resultServiceString = new ResultService<string>();
public ReturnObject<Book> GetBook()
{
return _resultServiceBook.GetGoodResult(new Book());
}
public ReturnObject<string> GetBookName(bookId)
{
return _resultServiceString.GetGoodResult(GetBookNameFromRepo(bookId));
}
}
As you can see, for every type that I want to return, I have to create a new instance of ResultService with that type. I can't seem to find a better way to accomplish this. I don't like that I have to create the same service multiple times like this to keep it type safe.
Just in case it is not clear what I mean when I say type safe, I mean that visual studio will catch type comparison while I'm still coding.
Upvotes: 1
Views: 4494
Reputation: 112602
There are two things you can do.
Add the generic type contraint new()
ensuring that the class has a parameter-less constructor and that you can call new
on T
.
Make the method generic.
public class GenericService
{
public ReturnObject<T> GetResult<T>()
where T : new()
{
return new ResultService<T>().GetGoodResult(new T());
}
}
If you don't want to create a new service each time, make the service a singleton
public class ResultService<T>
{
public static readonly ResultService<T> Instance = new ResultService<T>();
...
}
The generic service becomes
public class GenericService
{
public ReturnObject<T> GetResult<T>()
where T : new()
{
return ResultService<T>.Instance.GetGoodResult(new T());
}
}
Upvotes: 0
Reputation: 32053
You don't need to specify the generic type at the class level, as you don't have any state that depends on the generic being specified at that level. Instead, just specify the generic arguments on the methods.
Also, there's no reason to have that as a service, you are looking for the Factory pattern:
public static class ResultFactory
{
public static ReturnObject<T> GetGoodResult<T>(T result)
{
return new ReturnObject { Success = true, Result = result };
}
public static ReturnObject<T> GetGoodResult<T>(T result, IEnumerable<string> errors)
{
return new ReturnObject { Success = false, Errors = errors, Result = result };
}
}
You can then use this as simply as:
var data = new SomeClass();
var result = ResultFactory.GetGoodResult(data);
And result
will be a ReturnObject<SomeClass>
.
Upvotes: 4