2013-02-08 41 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

相關問題