Castle DynamicProxy - 创建涉及用作 GTR 的 GTP 的代理时失败
好吧,现在我真的很困惑。
我最初有 这个问题,根据发帖者的说法,这是 ILMerged 到最新 Rhino.Mocks 库中的 Castle.DynamicProxy 版本的问题。据有关该主题的几位权威人士称,该问题已在最新的 Castle 中得到修复,但该库尚未将其纳入新的 Rhino.Mocks 中。大多数人都说“只需下载 Rhino 源代码和最新的 Castle 并构建您自己的版本”。
所以,我确实这么做了;我从 Ayende 的 GitHub 上获取了 Rhino trunk 源代码的 ZIP,将其打开并构建了它。然后,像一个优秀的 TDDer 一样,我创建了一个单元测试来确保我的更改有效(因为最新的 Castle 将 DynamicProxy 折叠到 Core 中,需要一些重大的引用更改):
[Test]
public void MockOfInterfaceMethodWithInterfaceGTR()
{
var mock = mocks.DynamicMock<ITestRestrictedInterface>();
Assert.NotNull(mock);
Expect.Call(mock.TestMethod(new Object2())).IgnoreArguments().Return(5);
mocks.ReplayAll();
Assert.AreEqual(5, mock.TestMethod(new Object2()));
}
...
internal interface ITestGenericInterface<TRest> where TRest:IObject1
{
int TestMethod<T>(T input) where T : TRest;
}
internal interface ITestRestrictedInterface:ITestGenericInterface<IObject2> { }
internal interface IObject1 { }
internal interface IObject2:IObject1 { }
internal class Object2:IObject2 { }
当在我自己的生产代码中使用最新发布的版本运行时的结果犀牛?失败并显示以下消息:
System.TypeLoadException:类型上的方法“TestMethod” 'ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436' 来自 程序集'DynamicProxyGenAssembly2,版本= 0.0.0.0,文化=中性, PublicKeyToken=null'尝试隐式实现接口方法 具有较弱的类型参数约束。
...但是,当我将此测试复制并粘贴到 Rhino.Mocks.Tests 项目中的固定装置中,而不对引用的库进行任何更改时,测试通过了。我对下载的源代码进行了零更改。我对双方的测试方法和相关接口/对象进行了零更改。我构建了一个新的 Rhino.Mocks DLL(没有 IL 合并 Castle 库)并将其与 Castle 库一起复制回我的生产解决方案,重新运行测试,但仍然失败并显示相同的消息。
搞什么?
OK, now I'm really confused.
I originally had this problem, which is, according to posters, an issue with the version of Castle.DynamicProxy that's ILMerged into the latest Rhino.Mocks library. It has, according to several authorities on the subject, been fixed in the latest Castle, but that library has not made it into a new Rhino.Mocks. Most people are saying "just download the Rhino source and the latest Castle and build your own version".
So, I did exactly that; I grabbed a ZIP of the Rhino trunk source from Ayende's GitHub, opened it up, and built it. Then, like a good little TDDer, I created a unit test to make sure my changes worked (because the latest Castle folds DynamicProxy into Core, requiring some significant referencing changes):
[Test]
public void MockOfInterfaceMethodWithInterfaceGTR()
{
var mock = mocks.DynamicMock<ITestRestrictedInterface>();
Assert.NotNull(mock);
Expect.Call(mock.TestMethod(new Object2())).IgnoreArguments().Return(5);
mocks.ReplayAll();
Assert.AreEqual(5, mock.TestMethod(new Object2()));
}
...
internal interface ITestGenericInterface<TRest> where TRest:IObject1
{
int TestMethod<T>(T input) where T : TRest;
}
internal interface ITestRestrictedInterface:ITestGenericInterface<IObject2> { }
internal interface IObject1 { }
internal interface IObject2:IObject1 { }
internal class Object2:IObject2 { }
The result, when run in my own production code with the latest released Rhino? Failure with the following message:
System.TypeLoadException : Method 'TestMethod' on type
'ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436' from
assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null' tried to implicitly implement an interface method
with weaker type parameter constraints.
...However, when I copy and paste this test into a fixture in the Rhino.Mocks.Tests project, without making any changes to referenced libraries, the test PASSES. I have made zero changes to the downloaded source. I have made ZERO changes to the test method and related interfaces/objects on both sides. I built a new Rhino.Mocks DLL (without IL-merging the Castle libs) and copied it with Castle libs back to my production solution, re-ran the test, and it still fails with the same message.
WTF?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不是 Castle 专家,也不是编译器专家,但我相信这个问题是隐藏在 RhinoMocks.Tests 程序集中的一点魔法:
来自 https://github.com/ayende/rhino-mocks/blob/master/Rhino.Mocks.Tests/TestInfo.cs
为了完整起见,RhinoMocks.StrongName 定义为:
I使用 Moq 时也遇到过类似的问题,已记录此问题。
问题是 Castle 中的 DynamicProxy 需要动态派生新类型,但无法查看程序集内部的接口。只需将 InternalsVisibleTo 添加到 DynamicProxyGenAssembly2 到您的测试库即可解决问题。
I'm not a Castle expert nor compiler guru, but I believe the issue is a little bit of magic that is hidden inside the RhinoMocks.Tests assembly:
From https://github.com/ayende/rhino-mocks/blob/master/Rhino.Mocks.Tests/TestInfo.cs
And for completeness sake, RhinoMocks.StrongName is defined as:
I've seen a similar issue when using Moq, which has this issue documented.
The problem is that DynamicProxy in Castle needs to dynamically derive a new type but does not have visibility to see your interface which is internal to your assembly. Simply adding the InternalsVisibleTo to the DynamicProxyGenAssembly2 to your test library should solve the problem.