http://msdn.microsoft.com/en-us/library/system.runtime.remoting.proxies.realproxy.gettransparentproxy%28v=VS.100%29.aspx上的文档未指明GetTransparentProxy
将返回的方案null
,但是null
当我打电话给我时我会回来的.
什么情况会导致这种行为?
我一直在努力与WCF Proxies.处理WCF代理的正确方法是什么?答案并非微不足道.
System.ServiceModel.ClientBase违反了Microsoft自己的Dispose-pattern
System.ServiceModel.ClientBase<TChannel>
确实实现了,IDisposable
所以必须假设它应该在using
-block中处理或使用.这些是一次性用品的最佳实践.但是,实现是明确的,因此必须明确地将ClientBase
实例IDisposable
强制转换为使问题蒙上阴影.
混乱的最大来源,然而,就是呼吁Dispose()
对ClientBase
产生故障的情况下,甚至指责,因为他们从来没有摆在首位开渠道,将导致引发异常.这不可避免地意味着,当堆栈展开时,解释错误的有意义的异常会立即丢失,using
范围结束并Dispose()
抛出无意义的异常,表示您无法处置故障通道.
上述行为是对dispose模式的诅咒,该模式声明对象必须容忍多个显式调用Dispose()
.(请参阅http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx ,") 允许Dispose(bool)
多次调用该方法.该方法可能选择不执行任何操作第一次通话后. ")
随着控制反转的出现,这种糟糕的实现成为一个真正的问题.IOC容器(特别是Ninject)检测IDisposable
接口并Dispose()
在注入范围结束时显式调用激活的实例.
解决方案:代理ClientBase和Intercept调用Dispose()
我的解决方案是ClientBase
通过子类化代理System.Runtime.Remoting.Proxies.RealProxy
并劫持或拦截调用Dispose()
.我的第一个替换Dispose()
是这样的:
if (_client.State == CommunicationState.Faulted) _client.Abort();
else ((IDisposable)_client).Dispose();
Run Code Online (Sandbox Code Playgroud)
(注意,它_client
是对代理目标的类型引用.)
NetTcpBinding的问题
我认为这最初已经钉了它,但后来我发现生产中存在一个问题:在某些非常难以复制的情况下,我发现使用a的频道NetTcpBinding
在没有故障的情况下没有正确关闭,即使Dispose
被调用_client
.
我有一个ASP.NET MVC应用程序使用我的代理实现连接到NetTcpBinding
本地网络上的WCF服务,该服务托管在只有一个节点的服务集群上的Windows NT服务中.当我对MVC应用程序进行负载测试时,WCF服务上的某些端点(使用端口共享)会在一段时间后停止响应.
我努力重现这一点:在两台开发人员的机器之间运行在LAN上的相同组件运行良好; 锤击真正的WCF端点(在登台服务集群上运行)的控制台应用程序,其中包含许多进程和每个工作中的许多线程; 在登台服务器上配置MVC应用程序以连接到负载下工作的开发人员机器上的端点; 在开发人员的计算机上运行MVC应用程序并连接到暂存的WCF端点.然而,最后一种情况仅适用于IIS …
我正在RealProxy
.NET Core 中寻找替代品,这个问题将我转发到DispatchProxy
.
它有简单的API,但不清楚如何将现有对象包装到代理中。
例如,有这个界面:
interface IFoo
{
string Bar(int boo);
}
Run Code Online (Sandbox Code Playgroud)
和这个实现:
class FooImpl : IFoo
{
public string Bar(int boo)
{
return $"Value {boo} was passed";
}
}
Run Code Online (Sandbox Code Playgroud)
如何得到我想要的?
class Program
{
static void Main(string[] args)
{
var fooInstance = new FooImpl();
var proxy = DispatchProxy.Create<IFoo, FooProxy>();
var s = proxy.Bar(123);
Console.WriteLine(s);
}
}
class FooProxy : DispatchProxy
{
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
return targetMethod.Invoke(/* I …
Run Code Online (Sandbox Code Playgroud) 目标
我有几个接口和一些dll提供这些接口的实现.我要加载的实施进入一个新的AppDomain(这样我就可以卸载后的DLL)和instatiate在新的AppDomain执行,然后使用一个客户方(这里默认的AppDomain)代理来包装实际执行的对象.目标是创建这些ClientProxy
实例一次,并在不将实现程序集加载到默认AppDomain时更改其实际实现.
问题
在ClientProxy __TransparentProxy对象上调用另一个ClientProxy作为参数的方法时,我得到以下异常:
System.Runtime.Remoting.RemotingException:
'The argument type 'System.MarshalByRefObject' cannot be converted into parameter type 'IData'.'
内部异常:
InvalidCastException的: Object must implement IConvertible.
传递直接从Server AppDomain获取的__TransparentProxy时,ClientProxy可以正常工作.
建立
可以从以下网址获取:https://github.com/mailgerigk/remoting
接口:
public interface IData
{
int Foo { get; set; }
}
public interface ILogic
{
void Update(IData data);
}
Run Code Online (Sandbox Code Playgroud)
_impl.dll中的接口Impl:
public class DataImpl : MarshalByRefObject, IData
{
public int Foo { get; set; }
}
public class LogicImpl : MarshalByRefObject, ILogic
{
public void Update(IData …
Run Code Online (Sandbox Code Playgroud) 我试图通过a来处理泛型方法的调用RealProxy
,但我似乎无法找到有关截获的方法调用中使用的泛型参数的实际类型的信息.代码的摘录:
public override IMessage Invoke(IMessage msg)
{
...
string methodName = (string)msg.Properties["__MethodName"];
Type[] parameterTypes = (Type[])msg.Properties["__MethodSignature"];
object[] args = (object[])msg.Properties["__Args"];
MethodInfo method = typeToProxy.GetMethod(methodName, parameterTypes);
...
Run Code Online (Sandbox Code Playgroud)
假设我代理了一个类似的界面
interface IFactory
{
TService Create<TService>()
}
Run Code Online (Sandbox Code Playgroud)
当我打电话给代理
proxied.Create<MyClass>()
Run Code Online (Sandbox Code Playgroud)
我希望能够找出泛型参数的类型MyClass
.这可能通过RealProxy
吗?
我有一个透明代理,例如由WCF生成的代理:
ChannelFactory<ICalculator> channelFactory =
new ChannelFactory<ICalculator>(
new NetNamedPipeBinding(),
"net.pipe://localhost/WcfTransparentProxy/Calculator" );
ICalculator calculator = channelFactory.CreateChannel();
Run Code Online (Sandbox Code Playgroud)
如何从透明代理获取RealProxy?
在对RealProxy基础构造函数的调用中,传递要代理的目标对象的Type.我想要做的是动态地将接口添加到代理类型,以便可以将结果代理类型强制转换为其他接口.
例如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
namespace ConsoleApplication17
{
class Program
{
static void Main(string[] args)
{
MyProxy<IFoo> proxy = new MyProxy<IFoo>(new Foo());
IFoo proxiedFoo = (IFoo)proxy.GetTransparentProxy();
// make a proxied call...
proxiedFoo.DoSomething();
// cast proxiedFoo to IDisposable and dispose of it...
IDisposable disposableFoo = proxiedFoo as IDisposable;
// disposableFoo is null at this point.
disposableFoo.Dispose();
}
}
}
public interface IFoo
{
void DoSomething();
}
public class Foo : …
Run Code Online (Sandbox Code Playgroud) 我需要通过RealProxy调用带有ref-arguments的方法.我已将问题分解为以下代码:
using System;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
HelloClass hello=new HelloClass();
TestProxy proxy = new TestProxy(hello);
HelloClass hello2 = proxy.GetTransparentProxy() as HelloClass;
string t = "";
hello2.SayHello(ref t);
Console.Out.WriteLine(t);
}
}
public class TestProxy : RealProxy
{
HelloClass _hello;
public TestProxy(HelloClass hello)
: base(typeof(HelloClass))
{
this._hello = hello;
}
public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
{
IMethodCallMessage call = msg as IMethodCallMessage;
object returnValue = typeof(HelloClass).InvokeMember(call.MethodName, BindingFlags.InvokeMethod | BindingFlags.Public …
Run Code Online (Sandbox Code Playgroud)