表达式<;Func<;对象>>;作为流畅界面的一部分

本文关键字:gt lt 界面 一部分 Func 对象 表达式 | 更新日期: 2023-09-27 17:58:15

考虑这样的接口:

new Provider().For(myClass).ExcludeProperties("Height", "Width");
public IEditableStateProvider For(object target) {...}
public IEditableStateProvider ExcludePropertyNames(params string[] propertyNames) {...}

我想用params Expression<Func<object>>[] propertyNames替换params string[] propertyNames参数,这样我就可以得到以下内容。

new Provider().For(myClass).ExcludeProperties(()=>Height, ()=>Width);

我见过类似的代码,所以我认为应该工作,但我还没有得到它。我怎样才能让它发挥作用?

编辑-在没有Generics的情况下执行此操作

以下是一些来自开源项目的代码,我正在研究在没有任何泛型的情况下进行类型推理的情况。我也在想做同样的事情,但我不知道类型推断是从哪里来的(我看到它在工作!)

// USAGE (here this is being called from code-behind of a WPF window
private void TrackSelectedTab() {
    Services.Tracker.Configure(tabControl)
        .AddProperties(() => tabControl.SelectedIndex);
    Services.Tracker.ApplyState(tabControl);
}
private void TrackMainWindow() {
    Services.Tracker.Configure(this)
        .AddProperties(
            () => Height,
            () => Width,
            () => Left,
            () => Top,
            () => WindowState)
        .SetKey("MainWindow")
        .SetMode(PersistModes.Automatic);
    Services.Tracker.ApplyState(this);
}
// Collab classes
public class SettingsTracker
{   
    public TrackingConfiguration Configure(object target) {
        ...
        return config;
    }
}
public class TrackingConfiguration
{
    public TrackingConfiguration AddProperties(params Expression<Func<object>>[] properties) {
        ...
        return this;
    }
}
static class Services
{
    public static readonly SettingsTracker Tracker = new SettingsTracker(ObjectStore);
}

表达式<;Func<;对象>>;作为流畅界面的一部分

您应该在非泛型类的基础上创建一个泛型Provider类,这样您就可以利用类型推理和类型安全:

接口:

interface IEditableStateProvider<T>
{
     IEditableStateProvider<T> For(T target);
     IEditableStateProvider<T> ExcludePropertyNames(params Expression<Func<T, object>>[] excludedProperties);
} 

虚拟实现:

class Provider<T> : IEditableStateProvider<T>
{
    public IEditableStateProvider<T> For(T target) 
    { 
        // dummy
        return this;
    }
    public IEditableStateProvider<T> ExcludePropertyNames(params Expression<Func<T, object>>[] excludedProperties) 
    {
        // dummy
        return this;
    }
}
class Provider
{
    // generic factory method to make use of type inference
    public static IEditableStateProvider<T> For<T>(T obj)
    {
        return new Provider<T>().For(obj);
    }
}

用法:

var myClass = new List<object>(); // or whatever
Provider.For(myClass).ExcludePropertyNames(x => x.Count);

现在,当您调用.For(myClass)时,类型T是推断出来的,现在您可以在调用ExcludePropertyNames时通过lambda以类型安全的方式访问类型T的属性。


如果你真的想要一个非通用版本:

interface IEditableStateProvider
{
     IEditableStateProvider For(object target);
     IEditableStateProvider ExcludePropertyNames(params Expression<Func<object>>[] excludedProperties);
} 
class Provider : IEditableStateProvider
{
    public IEditableStateProvider For(object target) 
    { 
        // dummy
        return this;
    }
    public IEditableStateProvider ExcludePropertyNames(params Expression<Func<object>>[] excludedProperties) 
    {
        // dummy
        return this;
    }
}
var myClass = new List<object>();
new Provider().For(myClass).ExcludePropertyNames(() => myClass.Count);

但请注意我在下面的评论。