I have a Blazor server-side app where I use DynamicComponent on a page to create and add components at runtime. To do this I have the following:
A set of interfaces:
public interface IGetData{ Task GetDataAsync(string condition);}public interface IGetDataA : IGetData{ Task GetDataAsync(CriteriaA criteria);}public interface IGetDataB : IGetData{ Task GetDataAsync(CriteriaB criteria);}And then in the page (after creating the components):
public async Task RefreshAsync(){ var itemsA = items.Where(x => x.Ref.Instance is IGetDataA) .Select(x => x.Ref.Instance) .Cast<IGetDataA>(); await Parallel.ForEachAsync(itemsA, async (item, token) => { await item.GetDataAsync(criteriaA); }); var itemsB = items.Where(x => x.Ref.Instance is IGetDataB) .Select(x => x.Ref.Instance) .Cast<IGetDataB>(); await Parallel.ForEachAsync(itemsB, async (item, token) => { await item.GetDataAsync(criteriaB); });}Is it possible to unify the above into just one cast and one loop?
UPDATE
I've made changes to improve the code. I've simplified the interfaces as follows:
public interface IGetData<T> { Task GetDataAsync(string condition); Task GetDataAsync(T data);}And the code:
bool IsGetData(object o) => o.GetType().GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IGetData<>));var list = items.Where(x => IsGetData(x.Ref.Instance)) .Select(x => x.Ref.Instance);await Parallel.ForEachAsync(list, async (item, token) =>{ if (item is ItemA) await (item as ItemA).GetDataAsync(criteriaA); else if (item is ItemB) await (item as ItemB).GetDataAsync(criteriaB);});Now I have an extra helper method and also i need to use is and as. Is there a way to simplify the code further?