2013-02-08 58 views
0

的一部分ARG阵列考虑这样一个接口:表达<Func<object>>的流畅接口

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 ARG。

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

我见过类似这样的代码,所以我认为它应该工作,但我没有得到它。我怎样才能使这个工作?

编辑 - 这样做没有泛型

这里是一个开源项目,一些代码,我一直在寻找在那里类型推断的工作没有任何仿制药。我一直在寻找这样做,但我没有看到那里的类型推断是来自(我看到它虽然工作!)

// 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); 
} 

回答

3

您应该创造addittion通用Provider类非-generic一个,这样你就可以充分利用类型推理和类型安全的:

接口:

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现在infered,并调用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); 

但请注意,下面我的意见。

+0

我喜欢你的解决方案,但我正在考虑一个非通用的解决方案,沿着我原来的帖子编辑添加的代码行。你看到类型推断来自哪里?欢呼 – Berryl 2013-02-08 14:34:13

+1

您在编辑中发布的代码根本不使用类型推断。虽然它不是通用的,但它也不是类型安全的。没有什么能阻止你像使用'.Configure(tabControl).AddProperties((=> 12345);'(其中'int' 12345显然不是'tabcontrol'的属性)。它适用于'Height','Width'等等,因为这些属性是可访问的,因为'.AddProperties'被使用了一个具有这些属性的类(我猜它是一个'Form')。我强烈建议使用泛型方法,因为它确保您只能使用传递给For的类型/对象的属性。 – sloth 2013-02-08 14:49:02

+0

@Berryl尽管如此,我添加了一个非通用版本。 – sloth 2013-02-08 14:58:08

相关问题