Reputation: 65958
I have tried to write a generic method for the below mentioned code snippet.But it gives error on the OrderBy
clause ? Could you tell me why ?
var cache = RedisConnectorHelper.Connection.GetDatabase();
var values = JsonConvert.DeserializeObject<List<StateListDto>>(cache.StringGet(AppConsts.States));
if (values != null) return new ListResultOutput<StateListDto>(values.OrderBy(o => o.Name).ToList());
Generic method :
public ListResultOutput<T> GetCache<T>(string cacheKey)
{
var cache = RedisConnectorHelper.Connection.GetDatabase();
var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
return values != null ? new ListResultOutput<T>(values.ToList().OrderBy(o=>o.Name)) : null;
}
call :
var values = GetCache<StateListDto>(AppConsts.States);
StateListDto.cs
public class StateListDto
{
public string Code { get; set; }
public string Name { get; set; }
}
It gives this error: (click to see the full size image)
Upvotes: 0
Views: 146
Reputation: 507
You can send the way you want to order by as a parameter like this:
public ListResultOutput<T> GetCache<T>(string cacheKey, Func<T,object> selector)
{
var cache = RedisConnectorHelper.Connection.GetDatabase();
var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
return values != null ? new ListResultOutput<T>(values.OrderBy(selector).ToList()) : null;
}
call :
GetCache<StateListDto>("yourKey", i=>i.Name);
In this way you don't force your class to implement anything - and you can choose to order by other parameter in your code
Upvotes: 1
Reputation: 219037
But all are having Name property.
Then create a common interface for them, something like this:
public interface INamed
{
string Name { get; }
}
And all your models with that property can implement that interface:
public class StateListDto : INamed
Then you can use that interface as a type constraint on the generic method:
public ListResultOutput<T> GetCache<T>(string cacheKey) where T: INamed
That way the compiler can guarantee that the type of T
will have a Name
property.
Note that a base class, concrete or abstract, can also be used to accomplish this. Though personally I prefer to use interfaces over inheritance unless there's a specific reason to use inheritance.
Upvotes: 1
Reputation: 3751
If you are expecting to use this for more than just StateListDto
I would suggest creating an interface or base class that does have the property called Name
then you can guarantee it exists.
Something like:
public interface IDto
{
string Name { get; }
}
and then you can change your method to:
public ListResultOutput<T> GetCache<T>(string cacheKey) where T: IDto
{
var cache = RedisConnectorHelper.Connection.GetDatabase();
var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
return values != null ? new ListResultOutput<T>(values.ToList().OrderBy(o=>o.Name)) : null;
}
Upvotes: 2