2010-09-03 29 views
1

你會如何創建一個擴展方法,它使我做了以下(警告:exteme僞代碼)...在C#實現用VB聲明

class FooBar 
{ 
    Int32 Foo { get; set; } 
    String Bar { get; set; } 
} 

new FooBar().With(fb => new Func<FooBar, Object>(instance => 
{ 
    // VB With magic 
    // NOTE: The instance parameter HAS to be by reference 
    instance.Foo = 10; 
    instance.Bar; 

    return new Object(); 
})); 

如果你可以指定匿名函數不返回類型(void),上面看起來會更清晰...

new FooBar().With(fb => new Func<FooBar, void>(instance => 
{ 
    instance.Foo = 10; 
    instance.Bar; 
})); 

這是最糟糕的類型的僞代碼。但我希望你明白這一點。

回答

2

也許這將幫助:

new FooBar().With(fb=> { 
    fb.Foo = 10; 
    fb.Bar = fb.Foo.ToString(); 
}); 

// ... somewhere else ... 
public static void With<T>(this T target, Action<T> action) { 
    action(target); 
} 
+0

哦,快點!你先到那裏。 – Jamiec 2010-09-03 09:00:39

+0

所以'fb'是通過引用,而不是價值,是嗎? – roosteronacid 2010-09-03 09:03:59

+0

@roosteronacid - 假設'T'是一個類,那麼是的。如果你想強制執行這個方法,就會在'where T:class'方法上施加一個約束。見下面的答案。 – Jamiec 2010-09-03 09:05:34

1

如何只

return new FooBar{ Foo=10; }; 
+0

更新我的問題。我需要通過引用的實例。 – roosteronacid 2010-09-03 08:49:49

+0

對於曾經做過的人來說,當它提示問題更新時,我的答案會變得有些苛刻。現在可能與更多信息無關,但在當時是如此。 – 2010-09-03 09:30:11

4

要指定匿名方法沒有返回類型,使用Action<T>代替Func<T, TResult>

new FooBar().With(new Action<FooBar>(instance => 
{ 
    instance.Foo = 10; 
    instance.Bar; 
})); 

(我不太看在這種特殊情況下的點,但我對你的僞碼部分...)

更新
爲是完全 完整的示例:

擴展方法:

public static void With<T>(this T input, Action<T> action) 
{ 
    action(input); 
} 

使用範例

new FooBar().With(fb => 
{ 
    fb.Foo = 10; 
    fb.Bar = "some string"; 
}); 

請注意,您無需顯式聲明Action<FooBar>,編譯器的數字表示出來。如果你希望,爲清楚起見,呼叫是這樣的:

new FooBar().With<FooBar>(new Action<FooBar>(fb => 
{ 
    fb.Foo = 10; 
    fb.Bar = "some string"; 
})); 
+0

+1你快了幾秒 – 2010-09-03 08:52:39

+0

擴展方法如何? – roosteronacid 2010-09-03 08:57:06

+0

@roosteronacid:查看更新的答案。 – 2010-09-03 09:05:58

2

當你問到如何寫的擴展,在這裏不用

public static void With<T>(this T target, Action<T> action) where T : class 
{ 
    action(target); 
} 

個人沒有看到這有什麼好處,但填補你的靴子!

1

你會怎樣想的:

FooBar instance = new FooBar(); 

instance.With(new 
{ 
    Foo = 1, 
    Bar = "B" 
}); 

這可以由下面的擴展方法工作:

using System.Reflection; 

public static class WithExtension 
{ 
    public static T With<T>(this T target, object values) 
    { 
     Type targetType = typeof(T); 

     foreach (PropertyInfo prop in values.GetType().GetProperties()) 
     { 
      PropertyInfo targetProp = targetType.GetProperty(prop.Name); 

      if (targetProp != null && targetProp.PropertyType==prop.PropertyType) 
      { 
       targetProp.SetValue(target, prop.GetValue(values, null), null); 
      } 
      else 
      { 
       throw new InvalidOperationException(); 
      } 
     } 
     return target; 
    } 
} 

這本質上確實是抄襲了屬性的值從匿名對象目標對象。 (上面的代碼只適用於屬性,不適用於字段,但可以很容易擴展到能夠處理兩者。)

請注意,與使用lambdas相比,這樣做更簡單。缺點是靜態類型檢查不起作用。