Rem*_*anu 425 c# asp.net-mvc lambda mvccontrib
我正在看MvcContrib网格组件,我很着迷,但同时被网格语法中使用的语法技巧击退:
.Attributes(style => "width:100%")
Run Code Online (Sandbox Code Playgroud)
上面的语法将生成的HTML的style属性设置为width:100%.现在如果你注意,"风格"没有指定,是从表达式中参数的名称推断出来的!我不得不深入研究这个并发现"神奇"发生的地方:
Hash(params Func<object, TValue>[] hash)
{
foreach (var func in hash)
{
Add(func.Method.GetParameters()[0].Name, func(null));
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,代码使用正式的编译时,参数名来创建属性名称 - 值对的字典.结果语法结构确实非常具有表现力,但同时也非常危险.lambda表达式的一般用法允许替换使用的名称而没有副作用.我在一本书中看到一个例子,说collection.ForEach(book => Fire.Burn(book))我知道我可以用我的代码编写collection.ForEach(log => Fire.Burn(log)),这意味着同样的事情.但是使用MvcContrib网格语法突然间,我发现代码主动查找并根据我为变量选择的名称进行分解!
这是C#3.5/4.0社区和lambda表达爱好者的常见做法吗?或者是一个我不应该担心的流氓一招特立独行?
Mar*_*ell 154
我觉得奇怪的不是因为这个名字,而是因为lambda是不必要的 ; 它可以使用匿名类型并且更灵活:
.Attributes(new { style = "width:100%", @class="foo", blip=123 });
Run Code Online (Sandbox Code Playgroud)
这是在ASP.NET MVC的大部分中使用的模式(例如),并且有其他用途(需要注意的是,如果名称是魔术值而不是调用者特定,请注意Ayende的想法)
Bri*_*ian 146
这有很差的互操作性.例如,考虑这个C# - F#示例
C#:
public class Class1
{
public static void Foo(Func<object, string> f)
{
Console.WriteLine(f.Method.GetParameters()[0].Name);
}
}
Run Code Online (Sandbox Code Playgroud)
F#:
Class1.Foo(fun yadda -> "hello")
Run Code Online (Sandbox Code Playgroud)
结果:
印有"arg"(不是"yadda").
因此,库设计者应该避免这种"滥用",或者至少提供"标准"重载(例如,将字符串名称作为额外参数),如果他们想要在.Net语言之间进行良好的互操作.
Jer*_*ner 137
只是想提出我的看法(我是MvcContrib网格组件的作者).
这绝对是语言滥用 - 毫无疑问.但是,我不会真的认为它是反直觉的 - 当你看到一个电话时,Attributes(style => "width:100%", @class => "foo")
我认为很明显发生了什么(它肯定不比匿名类型方法更糟).从智能理论的角度来看,我同意这是非常不透明的.
对于那些感兴趣的人,在MvcContrib中使用它的一些背景信息......
我将此作为个人偏好添加到网格中 - 我不喜欢使用匿名类型作为词典(具有带"对象"的参数与采用params Func [])和Dictionary集合初始化器的参数一样不透明相当冗长(我也不喜欢冗长的流畅接口,例如必须将多个调用链接到一个Attribute("style","display:none").属性("class","foo")等)
如果C#对字典文字的语法不那么冗长,那么我就不会在网格组件中包含这种语法了.
我还想指出在MvcContrib中使用它是完全可选的 - 这些是包含带有IDictionary的重载的扩展方法.我认为重要的是,如果您提供这样的方法,您还应该支持更"正常"的方法,例如与其他语言互操作.
另外,有人提到了"反射开销",我只想指出这种方法确实没有太大的开销 - 没有涉及运行时反射或表达式编译(参见http://blog.bittercoder.com /PermaLink,guid206e64d1-29ae-4362-874b-83f5b103727f.aspx).
Not*_*Dan 49
我会比较喜欢
Attributes.Add(string name, string value);
Run Code Online (Sandbox Code Playgroud)
它更加明确和标准,并且使用lambdas没有获得任何东西.
Jas*_*yon 46
欢迎来到Rails Land :)
只要你知道发生了什么,它就没有什么不妥.(当这种事情没有很好地证明存在问题时).
整个Rails框架建立在约定优于配置的基础上.以某种方式命名事物可以将您锁定到他们正在使用的约定中,并且您可以免费获得大量功能.遵循命名约定可以让您更快地到达目的地.整个过程非常出色.
另一个我见过这样的技巧的地方是Moq中的方法调用断言.你传入一个lambda,但lambda永远不会被执行.他们只是使用表达式来确保方法调用发生,如果没有则抛出异常.
Sam*_*ron 42
这在多个层面上都很糟糕.不,这与Ruby不同.这是对C#和.Net的滥用.
关于如何以更直接的方式做到这一点有很多建议:元组,匿名类型,流畅的界面等等.
让它变得如此糟糕的原因在于它只是想要自己的好处:
当你需要从VB调用它时会发生什么?
.Attributes(Function(style) "width:100%")
它完全反直觉,智能感知将无法帮助确定如何传递内容.
它的效率不必要地低效.
没有人会知道如何维护它.
进入属性的参数类型是什么Func<object,string>?是吗?这个意图是如何揭示的.您的intellisense文档会说什么,"请忽略对象的所有值"
我认为你有这种反感的感觉是完全合理的.
Eli*_*sha 21
我几乎没有遇到过这种用法.我认为这是"不合适的":)
这不是一种常用的使用方式,它与一般惯例不一致.这种语法当然有利有弊:
缺点
优点
底线 - 在公共API设计中,我会选择更明确的方式.
Guf*_*ffa 18
不,这当然不常见.这是违反直觉的,没有办法只看代码来弄清楚它的作用.你必须知道如何使用它来理解它是如何使用的.
链接方法不是使用委托数组提供属性,而是更清晰,性能更好:
.Attribute("style", "width:100%;").Attribute("class", "test")
Run Code Online (Sandbox Code Playgroud)
虽然输入的内容多一点,但它清晰直观.
Tom*_*ier 17
以下是什么问题:
html.Attributes["style"] = "width:100%";
Run Code Online (Sandbox Code Playgroud)
Cha*_*ers 17
All this ranting about "horridness" is a bunch of long-time c# guys overreacting (and I'm a long-time C# programmer and still a very big fan of the language). There's nothing horrible about this syntax. It is merely an attempt to make the syntax look more like what you're trying to express. The less "noise" there is in the syntax for something, the easier the programmer can understand it. Decreasing the noise in one line of code only helps a little, but let that build up across more and more code, and it turns out to be a substantial benefit.
This is an attempt by the author to strive for the same benefits that DSL's give you -- when the code just "looks like" what you're trying to say, you've reached a magical place. You can debate whether this is good for interop, or whether it is enough nicer than anonymous methods to justify some of the "complexity" cost. Fair enough ... so in your project you should make the right choice of whether to use this kind of syntax. But still ... this is a clever attempt by a programmer to do what, at the end of the day, we're all trying to do (whether we realize it or not). And what we're all trying to do, is this: "Tell the computer what we want it to do in language that is as close as possible to how we think about what want it to do."
以与我们内部思考相同的方式接近向计算机表达我们的指令是使软件更易于维护和更准确的关键.
编辑:我曾说过"使软件更易于维护和更准确的关键",这是一种疯狂的过分夸大的单调性.我把它变成了"一把钥匙".
Jam*_*ney 12
这是表达式树的一个好处 - 可以检查代码本身以获取额外信息.那是怎样.Where(e => e.Name == "Jamie")才能转换成等效的SQL Where子句.这是表达树的巧妙使用,但我希望它不会比这更进一步.任何更复杂的东西都可能比它希望取代的代码更难,所以我怀疑它会自我限制.
这是一个有趣的方法.如果您将表达式的右侧约束为常量,那么您可以实现使用
Expression<Func<object, string>>
Run Code Online (Sandbox Code Playgroud)
我认为这是你真正想要的而不是委托(你使用lambda来获取双方的名字)参见下面的天真实现:
public static IDictionary<string, string> Hash(params Expression<Func<object, string>>[] hash) {
Dictionary<string, string> values = new Dictionary<string,string>();
foreach (var func in hash) {
values[func.Parameters[0].Name] = ((ConstantExpression)func.Body).Value.ToString();
}
return values;
}
Run Code Online (Sandbox Code Playgroud)
这甚至可以解决线程中前面提到的跨语言互操作问题.
小智 6
代码非常聪明,但它可能会导致更多问题解决.
正如您所指出的,现在参数名称(样式)和HTML属性之间存在模糊的依赖关系.没有编译时间检查.如果参数名称输入错误,页面可能不会有运行时错误消息,但更难找到逻辑错误(没有错误,但行为不正确).
更好的解决方案是拥有一个可以在编译时检查的数据成员.所以不是这样的:
.Attributes(style => "width:100%");
Run Code Online (Sandbox Code Playgroud)
编译器可以检查具有Style属性的代码:
.Attributes.Style = "width:100%";
Run Code Online (Sandbox Code Playgroud)
甚至:
.Attributes.Style.Width.Percent = 100;
Run Code Online (Sandbox Code Playgroud)
这对代码的作者来说更有用,但这种方法利用了C#强大的类型检查功能,这有助于防止错误首先进入代码.
实际上它看起来像Ruby =),至少对我来说,为后来的动态"查找"使用静态资源不适合api设计考虑因素,希望这个聪明的技巧在api中是可选的.
我们可以从IDictionary继承(或不继承)并提供一个索引器,当你不需要添加一个键来设置一个值时,它就像一个php数组.它将是.net语义的有效使用,而不仅仅是c#,仍然需要文档.
希望这可以帮助
恕我直言,这是一种很酷的方式.我们都喜欢这样一个事实,即命名一个类Controller会使它成为MVC中的控制器吗?因此,有些情况下命名很重要.
这里的意图也非常明确.很容易理解.Attribute( book => "something")会导致book="something"并.Attribute( log => "something")导致log="something"
我想如果你把它当成一种惯例,那应该不是问题.我认为无论是什么让你编写更少的代码并使意图明显是一件好事.
| 归档时间: |
|
| 查看次数: |
28378 次 |
| 最近记录: |