Я знаю, что могу вызвать универсальный метод, который напрямую принимает лямбда-выражение.
Например, в моем коде ниже я могу вызвать этот метод напрямую, но это не даст того, что мне нужно: GetAllItemsFromTableAsync (x => x.ID = 3)
Я хотел бы передать обобщенный метод в качестве делегата, и я хотел бы передать этому методу (или его производным) аргумент лямбда-выражения (фактически, фильтр базы данных), который в конечном итоге будетвызовите метод GetAllItemsFromTableAsync, предоставив необходимое выражение фильтра.
Можно ли передать метод в качестве делегата и предоставить лямбда-выражение для того же метода, когда он принимает такой как параметр?В моем коде вы увидите две примерные области, одна из которых работает в настоящее время (хотя она очень сильно упрощена по сравнению с исходным кодом, я не скомпилировал ее, но думаю, что она передает основную идею), другая пометка «не работает» - это то, что я хотел бынравится достигать тем или иным способом, если это даже возможно.В настоящее время это не так, так как я не могу понять, как ссылаться на аргумент, переданный для последовательного подключения его к другому методу.Можно ли это сделать?
Я немного новичок в лямбде и, честно говоря, все еще пытаюсь обернуть голову вокруг всего этого.Любая помощь будет принята с благодарностью.
#region This model does work currently (overly simplified for example purposes)
/// <summary>
/// Loads the various controls on the page that need special processing
/// </summary>
/// <returns></returns>
protected async Task RefreshControls()
{
await LoadPickerAsync<Car, ViewModel<Car>, List<Car>>(
this.GetPropertyInfo(x => x.AvailableColors),
this.GetPropertyInfo(y => y.ColorIndex),
this.GetPropertyInfo(z => z.Color),
LoadFromDBAsync<Colors, List<Colors>>);
await LoadPickerAsync<Truck, ViewModel<Truck>, List<Truck>>(
this.GetPropertyInfo(x => x.AvailableColors),
this.GetPropertyInfo(y => y.ColorIndex),
this.GetPropertyInfo(z => z.Color),
LoadFromDBAsync<Colors, List<Colors>>);
}
/// <summary>
/// This method is first stop in the load process. It sorts out the properties and then calls the
/// delegate method (in this example LoadFromDBAsync) to perform the actual loading of the picker list.
/// </summary>
/// <typeparam name="TColItemType"></typeparam>
/// <typeparam name="TViewModel"></typeparam>
/// <typeparam name="TCollection"></typeparam>
/// <param name="collectionProperty"></param>
/// <param name="indexProperty"></param>
/// <param name="objectProperty"></param>
/// <param name="collectionLoaderAsync"></param>
/// <returns></returns>
protected virtual async Task<TCollection> LoadPickerAsync<TColItemType, TViewModel, TCollection>(
PropertyInfo collectionProperty,
PropertyInfo indexProperty,
PropertyInfo objectProperty,
Func<Task<TCollection>> collectionLoaderAsync)
//Note I need to know how to pass a filter to the method here such as "x => x.ID = 2"
where TCollection : List<TColItemType>
{
//Do some special stuff with the properties
//Actually Load the picker
if (await collectionLoaderAsync() != default(TCollection))
{
//do something useful, set a flag etc...
}
}
/// <summary>
/// This method would be within each view model and may be totally different from one view
/// model to the next and even some controls may use their own method as long as the
/// basic signature remains the same
/// </summary>
/// <typeparam name="TColItemType"></typeparam>
/// <typeparam name="TCollection"></typeparam>
/// <returns></returns>
protected virtual async Task<TCollection> LoadFromDBAsync<TColItemType, TCollection>()
//I'd like to add a way for this method to pass a filter: "Expression<Func<TColItemType, bool>> filter = null"
where TCollection : List<TColItemType>, new()
where TColItemType : new()
{
//if I add the argument parameter to the method I can not figure out how to make the call
//to this method in LoadPickerAsync method above
//Expression<Func<T, bool>> filter = null,
//do some more stuff with the loading of the items into the picker
//Call the method to load the data and return
//note that "fitler" is only applicable if I can add the parameter above
return (TCollection)await GetAllItemsFromTableAsync<TColItemType>();
}
/// <summary>
/// Gets all data from the database table with the specified filter
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter"></param>
/// <param name="cancelToken"></param>
/// <returns></returns>
protected async Task<List<TColItemType>> GetAllItemsFromTableAsync<TColItemType>() where TColItemType : new()
{
//Do some prep work and null checks before calling the actual database method
//
//Call the database method to obtain the data
return await database.GetAllWithChildrenAsync<TColItemType>(recursive: true);
}
#endregion This model does work currently (overly simplified for example purposes)
#region Does NOT work
/// <summary>
/// Loads the various controls on the page that need special processing
/// </summary>
/// <returns></returns>
protected async Task RefreshControls()
{
await LoadPickerAsync<Car, ViewModel<Car>, List<Car>>(
this.GetPropertyInfo(x => x.AvailableColors),
this.GetPropertyInfo(y => y.ColorIndex),
this.GetPropertyInfo(z => z.Color),
LoadFromDBAsync<Colors, List<Colors>>(x => x.ID == 4));
await LoadPickerAsync<Truck, ViewModel<Truck>, List<Truck>>(
this.GetPropertyInfo(x => x.AvailableColors),
this.GetPropertyInfo(y => y.ColorIndex),
this.GetPropertyInfo(z => z.Color),
LoadFromDBAsync<Colors, List<Colors>>(x => x.ID == 3));
}
/// <summary>
/// This method is first stop in the load process. It sorts out the properties and then calls the
/// delegate method (in this example LoadFromDBAsync) to perform the actual loading of the picker list.
/// </summary>
/// <typeparam name="TColItemType"></typeparam>
/// <typeparam name="TViewModel"></typeparam>
/// <typeparam name="TCollection"></typeparam>
/// <param name="collectionProperty"></param>
/// <param name="indexProperty"></param>
/// <param name="objectProperty"></param>
/// <param name="collectionLoaderAsync"></param>
/// <returns></returns>
protected virtual async Task<TCollection> LoadPickerAsync<TColItemType, TViewModel, TCollection>(
PropertyInfo collectionProperty,
PropertyInfo indexProperty,
PropertyInfo objectProperty,
Func<Expression<Func<TColItemType, bool>>, Task<TCollection>> collectionLoaderAsync)
//Note I need to know how to pass a filter argument to the method here such as "x => x.ID = 2"
where TCollection : List<TColItemType>
{
//Do some special stuff with the properties
//With this overload example I can not figure out how to reference the argument passed in inorder to
//subsequently pass that argument when making the call to the method
//Actually Load the picker
await collectionLoaderAsync(filterArg);
}
/// <summary>
/// This method would be within each view model and may be totally different from one view
/// model to the next and even some controls may use their own method as long as the
/// basic signature remains the same
/// </summary>
/// <typeparam name="TColItemType"></typeparam>
/// <typeparam name="TCollection"></typeparam>
/// <returns></returns>
protected virtual async Task<TCollection> LoadFromDBAsync<TColItemType, TCollection>(
Expression<Func<TColItemType, bool>> filter = null)
//I'd like to add a way for this method to pass a filter: "Expression<Func<TColItemType, bool>> filter = null"
where TCollection : List<TColItemType>, new()
where TColItemType : new()
{
//if I add the argument parameter to the method I can not figure out
//how to make the call to this method in LoadPickerAsync method above
//Expression<Func<T, bool>> filter = null,
//do some more stuff with the loading of the items into the picker
//Call the method to load the data and return
//note that "fitler" is only applicable if I can add the parameter above
return GetAllItemsFromTableAsync<TColItemType>(filter);
}
/// <summary>
/// Gets all data from the database table with the specified filter
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filter"></param>
/// <param name="cancelToken"></param>
/// <returns></returns>
protected async Task<List<TColItemType>> GetAllItemsFromTableAsync<TColItemType>(
Expression<Func<TColItemType, bool>> filter = null) where TColItemType : Car, new()
{
//Do some prep work and null checks before calling the actual database method
//
//Call the database method to obtain the data
return await database.GetAllWithChildrenAsync<TColItemType>(recursive: true, filter: filter);
}
#endregion Does NOT work