好的,现在我真的很困惑.
我最初遇到这个问题,根据海报,问题是Castle.DynamicProxy的版本是ILMerged到最新的Rhino.Mocks库.据该主题的一些权威人士称,它已经在最新的城堡中得到了修复,但该库还没有成为新的Rhino.Mocks.大多数人都说"只需下载Rhino源代码和最新的Castle并构建自己的版本".
所以,我做到了这一点; 我从Ayende的GitHub抓起一个Rhino主干来源的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 { }
Run Code Online (Sandbox Code Playgroud)
结果,在我自己的生产代码中使用最新发布的Rhino运行?失败并显示以下消息:
System.TypeLoadException:来自程序集'DynamicProxyGenAssembly2,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null'的类型'ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436'上的方法'TestMethod'试图隐式地实现具有较弱类型参数约束的接口方法.
...但是,当我将此测试复制并粘贴到Rhino.Mocks.Tests项目中的fixture中时,不对引用的库进行任何更改,测试PASSES.我对下载的源进行了零更改.我对两侧的测试方法和相关接口/对象进行了ZERO更改.我构建了一个新的Rhino.Mocks DLL(没有IL合并Castle libs)并将它与Castle libs一起复制回我的生产解决方案,重新运行测试,它仍然失败并显示相同的消息.
WTF?
我正在寻找将逻辑添加到我正在处理的库中,这需要动态代理.我想从在生产环境中使用这两个库的用户那里得到一些建议.是否有一个人执行另一个,是否有任何缺点,使你必须切换到另一个,等等.基本上告诉我你的图书馆的经验.答案将帮助我决定使用哪一个.
- 编辑 -
我忘了提到我正在开发的图书馆将支持Mono,因此你可以分享关于这两个图书馆及其对Mono的支持的任何知识也会很棒.
下面是从代码Intercept
上实现自定义类型的方法IInterceptor
的的城堡动态代理库.此片段来自此处发布的基于AOP的日志记录概念验证控制台应用程序.
public void Intercept(IInvocation invocation)
{
if (Log.IsDebugEnabled) Log.Debug(CreateInvocationLogString("Called", invocation));
try
{
invocation.Proceed();
if (Log.IsDebugEnabled)
if (invocation.Method.ReturnType != typeof(void))
Log.Debug("Returning with: " + invocation.ReturnValue);
}
catch (Exception ex)
{
if (Log.IsErrorEnabled) Log.Error(CreateInvocationLogString("ERROR", invocation), ex);
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
这在常规方法调用中按预期工作,但在尝试使用async
方法时(使用async/await
C#5.0中的关键字)则不行.我相信,我也理解这背后的原因.
为了async/await
工作,编译器将方法的功能主体添加到幕后的状态机中,并且一旦awaitable
遇到无法同步完成的第一个表达式,控件将返回到调用者.
此外,我们可以询问返回类型并确定我们是否正在处理这样的async
方法:
if (invocation.Method.ReturnType == typeof(Task) ||
(invocation.Method.ReturnType.IsGenericType &&
invocation.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)))
Log.Info("Asynchronous method found...");
Run Code Online (Sandbox Code Playgroud)
这适用于那些async
返回Task
或Task<>
不返回的方法, …
我的问题与这篇文章有关拦截使用DynamicProxy调用异步方法
我想实现拦截器,它使用返回Task
或Task<T>
结果的异步方法.
我使用下一个代码返回ContinueWith
结果(以便在拦截器完成工作时调用方法等待)
var task = invocation.ReturnValue as Task;
invocation.ReturnValue = task.ContinueWith(c =>
{ code that should execute after method finish });
Run Code Online (Sandbox Code Playgroud)
上面的代码工作正常的Task
结果,但在的情况下,Task<T>
结果ContinueWith
将改变返回类型Task<T>
来Task
.我需要调用返回的重载方法ContinueWith Task<T>
,但为此我需要转换invocation.ReturnValue
为Task<T>
我没有找到以任何方式动态投射它的方法.有谁知道如何制作它?
我也尝试通过反射调用此方法,但参数是labmda函数,不能直接传递.
我写了一个这样的例子
简单计算器类:
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
Run Code Online (Sandbox Code Playgroud)
实现了DynamicProxy提供的"IInterceptor"
[Serializable]
public abstract class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
ExecuteBefore(invocation);
invocation.Proceed();
ExecuteAfter(invocation);
}
protected abstract void ExecuteAfter(IInvocation invocation);
protected abstract void ExecuteBefore(IInvocation invocation);
}
Run Code Online (Sandbox Code Playgroud)
创建了一个Interceptor类,并继承自"Interceptor"类
public class CalculatorInterceptor : Interceptor
{
protected override void ExecuteBefore(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("Start");
}
protected override void ExecuteAfter(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("End");
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我用它不工作!
static void Main(string[] args)
{
ProxyGenerator generator …
Run Code Online (Sandbox Code Playgroud) c# castle-dynamicproxy dynamic-proxy interceptor interception
我正在使用Castle DynamicProxy,我的ViewModel是一个代理,如下所示:
namespace MyApplication.ViewModels { public class MyViewModel : BaseViewModel, IMyViewModel { } }
我的viewmodel的代理看起来像这样:
{Name ="IRootViewModelProxyffecb133f590422098ca7c0ac13b8f98"FullName ="IRootViewModelProxyffecb133f590422098ca7c0ac13b8f98"}
我想获得被代理的实际类型的实际类型或命名空间.有没有办法做到这一点?我想要一些返回MyApplication.ViewModels.MyViewModel类型的东西.如果我使用concreate类作为代理,BaseType将返回正在代理的实际类,但在使用该接口时,BaseType将返回System.Object.
使用Castle的动态代理时,我遇到了一些(我认为)奇怪的行为.
使用以下代码:
class Program
{
static void Main(string[] args)
{
var c = new InterceptedClass();
var i = new Interceptor();
var cp = new ProxyGenerator().CreateClassProxyWithTarget(c, i);
cp.Method1();
cp.Method2();
Console.ReadLine();
}
}
public class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine(string.Format("Intercepted call to: " + invocation.Method.Name));
invocation.Proceed();
}
}
public class InterceptedClass
{
public virtual void Method1()
{
Console.WriteLine("Called Method 1");
Method2();
}
public virtual void Method2()
{
Console.WriteLine("Called Method 2");
}
}
Run Code Online (Sandbox Code Playgroud)
我期待获得输出:
我一直在使用一些基本的AOP风格解决方案来解决交叉问题,如安全性,日志记录,验证等.我的解决方案涉及Castle Windsor和DynamicProxy .我走了这条路,因为我可以使用基于Boo的DSL来应用所有内容,并保持我的代码清除属性.周末我被告知要看看PostSharp,因为它应该是一个"更好"的解决方案.我已经快速浏览了PostSharp,但是我被属性使用所拖延了.
有没有人尝试过两种解决方案,并愿意分享他们的经验?
只是想知道这些库之间的主要区别是什么,它们在特性和功能上有何不同.
希望获得比我在Google查询中找到的更多信息...
我被要求在我的asp.net Web应用程序中实现城堡动态代理,我正在阅读几篇文章,我从Castle Project和Code Project获得了关于asp.net web应用程序中的城堡动态代理....
这两篇文章都与创建拦截器有关,但是我无法理解为什么拦截器会与类一起使用....为什么我要拦截行为正常的类?
c# ×9
aop ×3
async-await ×2
interceptor ×2
reflection ×2
.net ×1
class ×1
generics ×1
interception ×1
postsharp ×1
proxy ×1
rhino-mocks ×1