2011-07-05 29 views
1

我有一個類似的方法需要:如何在重載的方法中傳遞各種表達式函數?

// takes in a DefaultValue type as an Expression Function, with an argument 
public void Register<T, TDefaultValueArgs>(Expression<Func<TDefaultValueArgs, T>> defaultValue) 
{ 
    // stuff happens here..... 
} 

我想補充的方法的兩個重載版本。其中defautlValue是T的簡單實例,另一個是defaultValue是沒有參數的表達式函數。

我想出這個(未經測試)解決方案:

// takes in a DefaultValue type 
public void Register<T>(T defaultValue) 
{ 
    // The statement below would be better, but isn't valid: "A lambda expression with a statement body cannot be converted to an expression tree" 
    // Expression<Func<object, T>> defaultValueFunc = (o) => { return defaultValue; }; 

    Expression<Func<DefaultValueContainer<T>, T>> defaultValueFunc = (m => m.GetDefaultValue(defaultValue)); 
    Register<T, DefaultValueContainer<T>>(defaultValueFunc); 
} 

// takes in a DefaultValue type as an Expression Function 
public void Register<T>(Expression<Func<T>> defaultValue) 
{ 
    // The statement below would be better, but isn't valid: "A lambda expression with a statement body cannot be converted to an expression tree" 
    // Expression<Func<object, T>> defaultValueFunc = (o) => { return defaultValue.Compile().Invoke(); }; 

    Expression<Func<DefaultValueContainer<T>, T>> defaultValueFunc = (m => m.GetDefaultValue(defaultValue)); 
    Register<T, DefaultValueContainer<T>>(defaultValueFunc); 
} 

private class DefaultValueContainer<T> 
{ 
    public DefaultValueContainer() 
    { } 

    public T GetDefaultValue(T defaultValue) 
    { 
     return defaultValue; 
    } 

    public T GetDefaultValue(Expression<Func<T>> defaultValue) 
    { 
     return defaultValue.Compile().Invoke(); 
    } 
} 

那麼我猜想,在我原來的Regsiter<T, TDefaultValueArgs>方法,我可以做這樣的事情:

T resolvedDefaultValue = default(T); 

if (typeof(TDefaultValueArgs).Equals(typeof(DefaultValueContainer<T>))) 
{ 
    var defaultValueContainer = Activator.CreateInstance<TDefaultValueArgs>(); 
    resolvedDefaultValue = defaultValue.Compile().Invoke(defaultValueContainer); 
} 

所有其中包括使用DefaultValueContainer<T>,似乎很愚蠢。一定會有更好的辦法?

注意:由於本示例範圍之外的原因,我需要使用表達式類型,而不僅僅是委託。

回答

0

您可以將您的lambda表達式更改爲表達式lambda表達式,而不需要包裝類。

您在代碼中想要的東西(但不工作):

Expression<Func<object, T>> defaultValueFunc = 
          (o) => { return defaultValue; }; 

你應該有什麼:

Expression<Func<object, T>> defaultValueFunc = 
          (o) => defaultValue; 

類似的,而不是:

Expression<Func<object, T>> defaultValueFunc = 
          (o) => { return defaultValue.Compile().Invoke(); }; 

你應該有:

Expression<Func<object, T>> defaultValueFunc = 
          (o) => defaultValue.Compile().Invoke(); 

進行這些更改應該允許您使用原始的Register<T>方法。

此外,我不確定這是否只是寫入問題的錯誤,但您可能希望對齊原始方法中的泛型類型參數,以便它們的順序與Func < >參數。不過,只是一種風格狡猾。

相關問題