用lambda去除Magic-String
string是我們的朋友。我們離不開string,但是有時候string也挺煩人的。
比如說,下面的代碼,根據方法名來獲取MethodInfo:
var info = typeof (DateTime).GetMethod("ToShortDateSting");
Console.WriteLine(info.Name);
Console.WriteLine(info.Name);
進行“Rename Method”重構時,重構工具是不會去對string進行重命名的。
我們不得不手動去一個一個改。如果漏了一個,我們也不能能當場知道,等到程序報錯時就太晚了!
我們可以通過lambda表達式,來獲取MethodInfo:
var info = Reflect.GetMethod<DateTime>(dt => dt.ToShortDateString());
Console.WriteLine(info.Name);
Console.WriteLine(info.Name);
同樣,我們可以獲取PropertyInfo:
var dayProperty = Reflect.GetProperty<DateTime>(dt => dt.Day);
Console.WriteLine(dayProperty.Name);
Console.WriteLine(dayProperty.Name);
下面是實現代碼:
public static class Reflect
{
public static MethodInfo GetMethod<TClass>(Expression<Action<TClass>> expression)
{
var methodCall = expression.Body as MethodCallExpression;
if(methodCall == null)
{
throw new ArgumentException("Expected method call");
}
return methodCall.Method;
}
public static PropertyInfo GetProperty<TClass>(Expression<Func<TClass, object>> expression)
{
MemberExpression memberExpression;
var unary = expression.Body as UnaryExpression;
if (unary != null)
{
memberExpression = unary.Operand as MemberExpression;
}
else
{
memberExpression = expression.Body as MemberExpression;
}
if (memberExpression == null || !(memberExpression.Member is PropertyInfo))
{
throw new ArgumentException("Expected property expression");
}
return (PropertyInfo) memberExpression.Member;
}
}
{
public static MethodInfo GetMethod<TClass>(Expression<Action<TClass>> expression)
{
var methodCall = expression.Body as MethodCallExpression;
if(methodCall == null)
{
throw new ArgumentException("Expected method call");
}
return methodCall.Method;
}
public static PropertyInfo GetProperty<TClass>(Expression<Func<TClass, object>> expression)
{
MemberExpression memberExpression;
var unary = expression.Body as UnaryExpression;
if (unary != null)
{
memberExpression = unary.Operand as MemberExpression;
}
else
{
memberExpression = expression.Body as MemberExpression;
}
if (memberExpression == null || !(memberExpression.Member is PropertyInfo))
{
throw new ArgumentException("Expected property expression");
}
return (PropertyInfo) memberExpression.Member;
}
}
更實用的例子是,MVC的RedirectToAction方法:
public class HomeController : Controller
{
public void Index()
{
if(!UserIsLoggedIn)
{
RedirectToAction("Login" );
}
}
public void Login()
{
}
}
{
public void Index()
{
if(!UserIsLoggedIn)
{
RedirectToAction("Login" );
}
}
public void Login()
{
}
}
用同樣的方法,上面的代碼,可以重寫為:
public class HomeController : Controller
{
public void Index()
{
if(!UserIsLoggedIn)
{
this.RedirectToAction(c => c.Login());
}
}
}
}
{
public void Index()
{
if(!UserIsLoggedIn)
{
this.RedirectToAction(c => c.Login());
}
}
public void Login()
{}
}
下面是實現代碼:
public static class ControllerExtensions
{
public static void RedirectToAction<TController>(this TController controller, Expression<Action<TController>> expression) where TController : Controller
{
var methodCall = expression.Body as MethodCallExpression;
if (methodCall == null)
{
throw new ArgumentException("Expected method call");
}
controller.RedirectToAction(methodCall.Method.Name);
}
}
{
public static void RedirectToAction<TController>(this TController controller, Expression<Action<TController>> expression) where TController : Controller
{
var methodCall = expression.Body as MethodCallExpression;
if (methodCall == null)
{
throw new ArgumentException("Expected method call");
}
controller.RedirectToAction(methodCall.Method.Name);
}
}
參考:http://blog.andreloker.de/post/2008/06/Getting-rid-of-strings-%282%29-use-lambda-expressions.aspx
注意:個人意見,僅供參考!
全站熱搜