After searching online and going through past stackoverflow posts for a suitable implementation for dynamic ordering with linq, i came up with my own implementation that borrows a few things from other solutions i have previously seen.
What i need to know is if this implementation is threadsafe? I don't believe it is as i am passing an enumerable generic type object (reference type) as a parameter into the static method but i would like to know if i am missing anything else and hopefully how to make it completely threadsafe.
public class OrderByHelper
{
开发者_如何学Go
public static IEnumerable<T> OrderBy<T>(IQueryable<T> items, string sortColumn, string sortDirection, int pageNumber, int pageSize)
{
Type t = typeof(T).GetProperty(sortColumn).PropertyType;
return (IEnumerable<T>)(typeof(OrderByHelper)
.GetMethod("OrderByKnownType")
.MakeGenericMethod(new[] { typeof(T), t })
.Invoke(null, new object[] { items, sortColumn, sortDirection, pageNumber, pageSize }));
}
public static IEnumerable<K> OrderByKnownType<K, T>(IQueryable<K> items, string sortColumn, string sortDirection, int pageNumber, int pageSize)
{
var param = Expression.Parameter(typeof(K), "i");
var mySortExpression = Expression.Lambda<Func<K, T>>(Expression.Property(param, sortColumn), param);
if (!string.IsNullOrEmpty(sortDirection))
{
if (sortDirection == "ASC")
return items.OrderBy(mySortExpression).Skip((pageNumber - 1) * pageSize).Take(pageSize);
else
return items.OrderByDescending(mySortExpression).Skip((pageNumber - 1) * pageSize).Take(pageSize);
}
else
throw new InvalidOperationException("No sorting direction specified.");
}
}
The answer is simple:
It is thread safe if your original collection is thread safe.
All extension methods in LINQ merely call .GetEnumerator()
of the original collection. Sorting and Ordering doesn't manipulate the original collection, but rather lets you enumerate it in a sorted order. Thus, you only do read operations on the data. As a general rule of thumb, if you only do read data, you do not need to implement any thread safety.
I'm tempted to say that in 99% of cases you don't need any thread safety, because you collect data only once and then expose the LINQ functionality. You might only need a thread safe collection if you want to create a framework that does not instantiate new collections when refreshing data, but rather keeps re-using the same (observable) collection instance that synchronizes itself with the database data in a fancy way.
But I don't know about your exact scenario. If you really do need thread safety, then it depends if you have control over the code where the original collection is instantiated and the data is added.
If you are using merely LINQ-to-objects, then it's entirely in your control to create an instance of a thread safe collection class at that spot.
If you're using LINQ-to-SQL or anything, then it might be difficult because the original collection that collects the data from the database is probably instantiated deep within the provider and hidden from you. I haven't looked at it though if there are extension points where you can override stuff to use a thread safe collection instead.
精彩评论