gpt4 book ai didi

c# - 如何使方法可重用于不同类型

转载 作者:太空宇宙 更新时间:2023-11-03 21:10:38 25 4
gpt4 key购买 nike

我在 Visual Studio 2015 中使用 MVVM Light 构建 WPF 应用程序。代码中有一个方法在代码中重复了 4 次,但略有不同;唯一的区别是被修改的 ObservableCollection 的类型和在数据服务层调用的方法。

这是方法,它返回 StatusViewModel 对象的 ObservableCollection,这些对象用于填充 ComboBoxStatusVm 用于绑定(bind)到 ComboBoxSelectedItem,设置为集合中的第一项,并且为“空白”:

private async Task<ObservableCollection<StatusViewModel>> GetStatuses()
{
var result = new ObservableCollection<StatusViewModel>();
var blank = new StatusViewModel
{
StatusId = -1,
Status = null,
Description = null,
IsActive = false,
CreatedDate = DateTime.Now
};
result.Add(blank);
var dataService = new MyDataService();
foreach (var c in await dataService.GetStatuses())
result.Add(c);
StatusVm =
result.SingleOrDefault(c => c.StatusId.Equals(-1));
return result;
}

这是 StatusVm 的私有(private)字段和公共(public)属性:

private StatusViewModel _statusVm;
public StatusViewModel StatusVm
{
get { return _statusVm; }
set
{
if (Equals(value, _statusVm)) return;
_statusVm = value;
RaisePropertyChanged();
}
}

现在想象上面的内容再重复 3 次,还有 3 种 VM 类型!如何将 GetStatuses() 变成一个可以采用不同 View 模型类型并在数据服务上调用适当方法的方法?谢谢。

更新:这是另一种类型的属性和方法:

private MroViewModel_mroVm;
public MroViewModel MroVm
{
get { return _mroVm; }
set
{
if (Equals(value, _mroVm)) return;
_mroVm = value;
RaisePropertyChanged();
}
}

private async Task<ObservableCollection<MroViewModel>> GetMro()
{
var result = new ObservableCollection<MroViewModel>();
var blank = new MroViewModel
{
StatusId = -1,
Status = null,
Description = null,
IsActive = false,
CreatedDate = DateTime.Now
};
result.Add(blank);
var dataService = new MyDataService();
foreach (var c in await dataService.GetMro())
result.Add(c);
MroVm =
result.SingleOrDefault(c => c.StatusId.Equals(-1));
return result;
}

最佳答案

您将为公共(public)属性创建接口(interface)。

internal interface IStatusViewModel {
int StatusId { get; set; }
string Status { get; set; }
string Description { get; set; }
bool IsActive { get; set; }
DateTime CreatedDate { get; set; }
}

在需要检索状态的类中实现接口(interface)

internal class MroViewModel : IStatusViewModel {
public int StatusId { get; set; }
public string Status { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedDate { get; set; }
}

将方法设为静态并传递服务函数,该函数将调用适当的方法来检索旧状态。

public static async Task<ObservableCollection<T>> GetStatuses<T>(
Func<MyDataService, Task<IEnumerable<T>>> retrieveStatusesAction)
where T : IStatusViewModel, new()
{
var result = new ObservableCollection<T>();
var blank = new T
{
StatusId = -1,
Status = null,
Description = null,
IsActive = false,
CreatedDate = DateTime.Now
};
result.Add(blank);

var dataService = new MyDataService();
foreach (var c in await retrieveStatusesAction(dataService))
result.Add(c);

// TODO Implement Expression<Func<TSource, TResult>> projection for assigning to VM
StatusVm = result.SingleOrDefault(c => c.StatusId.Equals(-1));

return result;
}

然后你可以像这样调用这个方法:

GetStatuses((service) => service.GetMro());

我没有对此进行测试,需要使用表达式编译来分配 StatusVm。我现在将看看如何做到这一点,但想法就在那里。

对于表达式和属性分配: Property selector Expression<Func<T>>. How to get/set value to selected property

-- 编辑--

像这样的 VM 分配:

    public static async Task<ObservableCollection<T>> GetStatuses<T, TContainer>(
TContainer instance,
Expression<Func<TContainer, T>> viewModelProjection,
Func<MyDataService, Task<IEnumerable<T>>> retrieveStatusesAction)
where T : IStatusViewModel, new()
{
var result = new ObservableCollection<T>();
var blank = new T
{
StatusId = -1,
Status = null,
Description = null,
IsActive = false,
CreatedDate = DateTime.Now
};
result.Add(blank);

var dataService = new MyDataService();
foreach (var c in await retrieveStatusesAction(dataService))
result.Add(c);

var vmStatus = result.SingleOrDefault(c => c.StatusId.Equals(-1));

// Warning: Check casted values, this is unsafe
var vm = (PropertyInfo)((MemberExpression)viewModelProjection.Body).Member;
vm.SetValue(instance, vmStatus, null);

return result;
}

然后您将像这样调用该方法:

await GetStatuses(this, inst => inst.MroVm, (service) => service.GetMro());

如果你不熟悉表达式,我会解释。第一个参数是 View 模型实例所在的对象。第二个参数从与需要更改的 View 模型相对应的对象中选择属性。最后一个参数是获取服务并返回检索状态的适当方法的函数 - 这就像指向 C++ 中的函数的指针。

这将编译,但不确定它是否会按预期运行。它应该。如果您有任何问题,请在评论中写下来。

关于c# - 如何使方法可重用于不同类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37994884/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com