說我有一些像這樣的方法:使用Expression API,有沒有辦法將Func <T>與另一個「組合」?
public void Method<T>(Func<T> func)
{
...
}
有沒有我可以使用Expression
API,有效地注入一些代碼在傳遞Func
運行的代碼之前要運行什麼辦法?意思是,在我的方法中,我不會實際執行Func
,而是將其分配給一個將調用Func
的對象的某個屬性。我只想在運行代碼之前運行一些代碼。此外,我的代碼是否可以從Func
「返回」,以便傳入的代碼永遠不會運行?
編輯:好的,我擔心這還不夠。這是我想要做的。使用Moles,你可以將你的代碼中的任何呼叫存檔。所以說,我有一個調用像這樣一個靜態方法,一些不可測代碼:
FileSystem.ReadAllText(string fileName);
痣會創建一個存根/摩爾對象(無論術語),我就可以使用存根出的方法,所以當我的代碼調用ReadAllText,它會叫我的存根:
MFileSytem.ReadAllTextString = s => return "content";
非常酷的東西,但是我想這種想法擴展,這樣我可以用它類同一個典型的模擬框架(如MOQ)所以只有當傳入的參數是一個特定的值時,或者可能驗證一個方法只被調用一次時,我纔可以刪除該方法。以下是我到目前爲止:
仍然非常粗魯!
public static class Extensions
{
public static void TestWithMoles<T, U, V>(this T item, Expression<Func<U, V>> expression, MolesDelegates.Func<U, V> stub)
{
var methodCallExpression = expression.Body as MethodCallExpression;
if (methodCallExpression != null)
{
var method = methodCallExpression.Method;
var returnType = method.ReturnType.Name;
var assemblyName = method.DeclaringType.Assembly;
var assmebly = GetMolesAssmeblyName(assemblyName.GetName().Name);
var type = assmebly.GetTypes().FirstOrDefault(t => t.Name == "M" + method.DeclaringType.Name);
var property = type.GetProperties(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(p => p.Name == method.Name + returnType);
property.SetValue(item, stub, null);
}
}
private static Assembly GetMolesAssmeblyName(string assemblyName)
{
var entryAssembly = Assembly.GetExecutingAssembly();
foreach (var assembly in entryAssembly.GetReferencedAssemblies())
{
if (assembly.Name == assemblyName)
{
continue;
}
if (assembly.Name.Contains(assemblyName) && assembly.Name.Contains(".Moles"))
{
return Assembly.Load(assembly.FullName);
}
}
return null;
}
}
現在的想法是,如果我有這樣一個類:
public class TestReader
{
public string Content { get; private set; }
public void LoadFile(string fileName)
{
var content = FileSystem.ReadAllText(fileName);
if (!content.StartsWith("test"))
{
throw new ArgumentException("invalid file");
}
this.Content = content;
}
}
我現在可以這樣做:
[TestMethod]
[HostType("Moles")]
public void CheckValidFilewithMoles()
{
//arrange
var fileName = "test.txt";
var content = "test";
//act
var test = new TestReader();
test.TestWithMoles<TestReader, string, string>(s => FileSystem.ReadAllText(s), s =>
{
Assert.IsTrue(s == fileName);
return content;
});
test.LoadFile(fileName);
//assert
Assert.AreEqual(content, test.Content);
}
到目前爲止好,但我沒有完成任何事情。我想要做的是,在我的擴展方法,當我這樣做:
property.SetValue(item, stub, null);
將設置痣委託無論是進去時,我想先「注入」一些代碼,讓我可以看看有哪些正在傳遞的價值觀,我可以添加一些數據字典的一些跟蹤方法調用的計數等
希望這是現在更有意義......
目前還不清楚表達式API的用途 - 您已經提供了方法簽名,但僅此而已。你已經討論過將'Func'分配給某個屬性,但是這並不需要使用表達式API ...請給我們更多的信息。 –
@Jon Skeet:看編輯。讓我知道你是否需要更多的澄清。 – BFree