看this问题让我想知道使用C#的暗反射方式是否可能有类似的东西。
说我有这段代码:
public class Foo
{
public void FooPrint() // can't change this implementation
{
Console.Write("Foo");
}
}
public class Bar
{
public Foo foo = new Foo();
public Bar()
{
//do some reflection magic with member foo here ?
}
public void FooPrintRewritten()
{
Console.Write("Haha, only for Bar.foo.");
}
}
class Program
{
static void Main(string[] args)
{
Foo a = new Foo();
a.FooPrint(); // should still print "Foo"
Bar bar = new Bar();
bar.foo.FooPrint(); // should print "Haha, only for Bar.foo."
}
}
我在内联评论中以任何可能的方式提出的要求是什么?有没有办法将方法调用重新绑定到另一个方法只用于特定变量?
是的我知道这很荒谬,不应该在生产代码中使用它。这是为了好奇。
答案 0 :(得分:1)
这个怎么样,仍有相同的用法:
{{1}}
答案 1 :(得分:1)
实际上,如果您需要单独实现以维护原则(取决于您遵守SOLID ofc的严格程度),则在SOLID的SRP下存在此类行为的情况。
它被称为拦截器模式,由Mocking库使用,例如Moq。
有关如何使用该模式的一个很好的示例,请查看以下关于该主题的文章:C#: Why Decorate When You Can Intercept
答案 2 :(得分:1)
这是在实例化类
时覆盖(虚拟)方法的另一种方法class Program
{
static void Main(string[] args)
{
Foo a = new Foo();
a.FooPrint(); // should still print "Foo"
Bar bar = new Bar();
bar.foo.FooPrint(); // should print "Haha, only for Bar.foo."
Console.Read();
}
}
public class Foo
{
public Action FooPrint = () => Console.WriteLine("Foo");
}
public class Bar
{
public Foo foo = new Foo()
{
FooPrint = () => Console.WriteLine("Haha, only for Bar.foo.")
};
}
this帖子解释了在实例化类时如何正确覆盖。
但是,它使用 Func ,这需要一个包含无效返回类型的方法,这就是为什么你要使用 Action ,而不是{{ 3}}
答案 3 :(得分:1)
其他答案已经提出了一些方法,你可以在功能层面上实现你想要的东西,这可以说是理智的事情,但我会直接解决这个问题:这可以改变吗?问题除了Bar.Bar()
的实施,保留Bar.foo
类型Foo
并且不更改Foo
时的任何内容?
答案是否定的。您无法更改单个对象的方法表,这基本上是您在此处要求的。方法表是类型的一部分,而不是实例。如果表达式f
的类型为Foo
,而FooPrint
是Foo
的非虚方法,则调用f.FooPrint()
将始终解析为{{ 1}}。更糟糕的是,编译器可能会选择内联调用,因为这显然是一个安全的优化 * 。现在你的黑暗反射方式在哪里?
实现这一目标的唯一方法是说服编译器应该特别对待Foo.FooPrint
的调用,并考虑实例。有几种方法可以这样做:
Foo.FooPrint
可以成为代表。委托调用的目标是每个委托实例特定的。Foo.FooPrint
可以成为虚拟,抽象或接口方法。所有这些都是基于实例的运行时类型来解决的。只需从Foo.FooPrint
派生一个课程即可离开。Foo
可以继承自Foo
。 MBRO(通常称为MBRO)由抖动专门处理,因为(顾名思义)可能需要对调用进行编组。特别是,如果MarshalByRefObject
是一个MBRO,你可以为它创建一个RealProxy
,它会在几乎所有方面咳出一个类似真实的Foo
的透明代理,直到Foo
,但您必须选择实际处理呼叫的方式。所有这些方法都被各种模拟/拦截器/代理库使用,所有这些都需要某些更改为GetType()
。唯一不需要(文本)更改Foo
的方法是那些重写IL所涉及的方法,比如PostSharp或Microsoft Fakes,但我认为这个问题的目的是作弊。
* 从技术上讲,C#标准没有提及任何方法表或允许的内联方式,因为这些是实现细节,但确实说Foo
总是只用一种方式解决不考虑实例(除了它不能是Foo.FooPrint
)。