我对理论方面很感兴趣。在典型的日常编程场景中,C#在运行时使用Codedom / Reflection或Lambda表达式/表达式树来生成代码需要什么?不是在特殊情况下
或者像Ruby这样的其他语言,为什么要在运行时使用monkeypatching来添加/修改类?
这有什么优势?
答案 0 :(得分:2)
在Ruby中,生成方法的方法无处不在。
例如,有生成setter和getter方法的方法:
class Module
def attr_reader(*attributes)
attributes.each do |attribute|
define_method(attribute) do instance_variable_get(:"@#{attribute}") end
end
end
def attr_writer(*attributes)
attributes.each do |attribute|
define_method(:"#{attribute}=") do |value|
instance_variable_set(:"@#{attribute}", value)
end
end
end
def attr_accessor(*attributes)
attr_reader(*attributes)
attr_writer(*attributes)
end
end
当我调用这样的方法之一时:
attr_reader :bla
这将生成一个名为bla
的方法,该方法返回名为@bla
的实例变量的值。
和
attr_writer :bla
将生成一个名为bla=
的方法(在末尾用等号命名方法是Ruby中setter的通常命名约定),它将其参数赋给名为@bla
的实例变量。< / p>
class Foo
attr_reader :foo, :bar
attr_writer :baz, :quux
attr_accessor :gargle, :blarf
end
这将生成方法foo
,bar
,baz=
,quux=
,gargle
,gargle=
,blarf
,{ {1}}。
另一个例子是Ruby的blarf=
ORM库,它基于在运行时反映数据库模式,为模型生成getter和setter方法以及finder方法。
ActiveRecord
也有动态查找程序方法,可让您执行ActiveRecord
之类的操作。当然,人们可能想要搜索的数据库列有无限多种组合,因此提前生成所有方法是不切实际的。相反,Person.find_by_name_and_age('John', 42)
会安装ActiveRecord
挂钩来拦截对以method_missing
开头的不存在方法的调用。但是,一旦它截获了一个方法调用,它就会生成一个该名称的方法,假设该方法可能在时间内被更频繁地调用,因此动态拦截可以是侧面步骤。
一般来说, Code Synthesis 在代码生成有用的任何地方都很有用,但具有显着优势
答案 1 :(得分:1)
我遇到过几个案例。一个案例是出于性能原因。例如当您存储创建对象的已编译委托时。比如一些IoC框架。这些编译后的代表往往创建起来很慢,但如果多次调用相同的委托,执行速度非常快可以提供良好的性能提升。
我遇到的另一个案例是使用谓词构建动态过滤器,然后在数据库中序列化这些过滤器,以便用户不需要再次定义它们。
答案 2 :(得分:1)
有时你必须牺牲完整的清洁代码来获得大量的生产力和进化。
例如,如果您开发了1000个类并为每个类创建二进制序列化程序。通过反射和代码生成来实现它非常容易。与许多静态代码相比,维护独特的动态代码要困难得多。在对动态代码进行完全认证后,风险实际上已降至最低。
幸运的是,通用涵盖了这个问题的很大一部分。
在处理一个小项目时,在运行时生成msil是没用的。
另一个考虑因素是水平发展(公用事业/帮助者)不依赖于直接业务发展。