积极答复者
.net Remoting 的问题

问题
-
现在的结构是这样的表A,B,C接口IA,IB,IC分别是对表A,B,C的操作对应的实现有Aimpl,Bimpl,Cimpl宿主是IIS,在配置文件中
<wellknown mode="SingleCall" type="MySystem.impl" objectUri="Aimpl.rem"/>
<wellknown mode="SingleCall" type="MySystem.impl" objectUri="Bimpl.rem"/>
<wellknown mode="SingleCall" type="MySystem.impl" objectUri="Cimpl.rem"/>
这样每加一个实现就要加一个配 置,目前已经有60左右了.
现在突然说这样不好维护,要把所 有的结口改成一个,放到一个接口里.
IA,IB,IC,有一些接口是 一统一的比如添加,修改等接口名称是一样的.
如果要改,60个类,是很恐怖 的.而且系统可能会改出新的问题.
主要问题是这个配置文件,每次有增加都要改,领导怕麻烦.
无
答案
-
根据下面这个地址,你的服务可以按版本号和表名归类:
http://localhost/service1-0/a.rem
匹配规则: 基址 + 版本号 + 表名 + “.rem”;
RemotingConfiguration.RegisterWellKnownServiceType(t,t.Name + ".rem", WellKnownObjectMode.SingleCall);
下划线部分要加前置 "http://localhost/service1_0/"+t.Name+".rem".http://localhost/service1_0/ 放到配置文件中 <AppSetting name="BaseUri" value="http://localhost/service1_0/"/>
- 已标记为答案 male110 2010年5月31日 0:43
全部回复
-
Assembly asb = Assembly.LoadFile(strPath);
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel,false);
//反射获取类型
Type[]tps=asb.GetExportedTypes();
foreach (Type t in tps)
{
if (t.Name.Length <= 4 && t.Name.Substring(t.Name.Length - 4) != "Impl")
continue;
RemotingConfiguration.RegisterWellKnownServiceType(t,t.Name + ".rem", WellKnownObjectMode.SingleCall);
}改成这样不行,现在的客户端是通过,http://localhost/service/a.rem这样的路径来获取远程对象的,这是测试时的客户端.
正式的又有版本问题http://xxxx/service1_0/a.rem 1.0版本
http://xxxx/service1_3/a.rem 1.3版本
有没有更好的办法?
无 -
可能你的修改你的服务端,使用工厂模式激活,相关的实现,这里有:
http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html
你可以仔细读下。
-
Assembly asb = Assembly.LoadFile(strPath);
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel,false);
//反射获取类型
Type[]tps=asb.GetExportedTypes();
foreach (Type t in tps)
{
if (t.Name.Length <= 4 && t.Name.Substring(t.Name.Length - 4) != "Impl")
continue;
RemotingConfiguration.RegisterWellKnownServiceType(t,t.Name + ".rem", WellKnownObjectMode.SingleCall);
}改了,不行,改成代码了,跟原来的地址对不上.
IIS宿主的.且不家版本问题,不知道怎么改了.
无 -
根据下面这个地址,你的服务可以按版本号和表名归类:
http://localhost/service1-0/a.rem
匹配规则: 基址 + 版本号 + 表名 + “.rem”;
RemotingConfiguration.RegisterWellKnownServiceType(t,t.Name + ".rem", WellKnownObjectMode.SingleCall);
下划线部分要加前置 "http://localhost/service1_0/"+t.Name+".rem".http://localhost/service1_0/ 放到配置文件中 <AppSetting name="BaseUri" value="http://localhost/service1_0/"/>
- 已标记为答案 male110 2010年5月31日 0:43
-
string strBaseUri = ConfigurationManager.AppSettings["baseUri"];
strBaseUri=strBaseUri.Replace("{version}",Constants.Version.Replace(".","_"));
Assembly asb = Assembly.LoadFile(strPath);
HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel, false);
//反射获取类型
Type[] tps = asb.GetExportedTypes();
foreach (Type t in tps)
{
if (t.Name.Length <= 4 && t.Name.Substring(t.Name.Length - 4) != "Impl")
continue;
RemotingConfiguration.RegisterWellKnownServiceType(t,strBaseUri+ t.Name + ".rem", WellKnownObjectMode.SingleCall);
}protected void Application_Start(object sender, EventArgs e)
{RegisterService();
}
通过查看日志发现
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/FaqQuestionImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/EmailTemplateImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/RolesImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/RoleFaqCategoryImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/RelativeProductTagImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/ProductsTagFilterImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/GenerateHomePageImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/ForumTagImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - http://localhost/TinydealWinRemote/AddressBookImpl.rem, 已注册成功
2010-05-31 10:06:03,515 [8] WARN Log - 服务已注册服务是注册的,但是在创建的时候就是出错,创建时的URL跟注册的一样.
无 -
public UserInfosServiceHelper()
{
String strUrl = Path.Combine(LogicBaseInfo.WebserviceUrl, "UserInfosImpl.rem").Replace("\\", "/");
_Service = (IUserInfos)Activator.GetObject(typeof(IUserInfos), strUrl);
}这里是创建远程对象,这里的strurl跟注册的一模一样.这个是在构造函数里
然后用这个类的实例调用方法时就会出错.
System.Runtime.Remoting.RemotingException: ???????????????????????????????????????System.Runtime.Remoting.RemotingException: ?????????http???????????????
??? System.Runtime.Remoting.Channels.ChannelServices.RegisterChannelInternal(IChannel chnl, Boolean ensureSecurity)
??? System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(IChannel chnl, Boolean ensureSecurity)
??? System.Runtime.Remoting.RemotingConfigHandler.ConfigureChannels(RemotingXmlConfigFileData configData, Boolean ensureSecurity)
??? System.Runtime.Remoting.RemotingConfigHandler.ConfigureRemoting(RemotingXmlConfigFileData configData, Boolean ensureSecurity)??????
??? System.Runtime.Remoting.RemotingConfigHandler.ConfigureRemoting(RemotingXmlConfigFileData configData, Boolean ensureSecurity)
??? System.Runtime.Remoting.RemotingConfigHandler.DoConfiguration(String filename, Boolean ensureSecurity)
??? System.Runtime.Remoting.RemotingConfiguration.Configure(String filename, Boolean ensureSecurity)
??? System.Runtime.Remoting.Channels.Http.HttpRemotingHandler.InternalProcessRequest(HttpContext context)
Server stack trace:
Exception rethrown at [0]:
在 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
在 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
在 TinydealWin.Interfaces.IUserInfos.Exists(UserIdentity user, Int32 id)
在 TinydealWin.Logic.UserInfosServiceHelper.Exists(Int32 id) 位置 E:\projects\TinydealWin\Projects\TinydealWin.Logic\UserInfosServiceHelper.cs:行号 21
在 TinydealWin.Program.Main() 位置 E:\projects\TinydealWin\Projects\TinydealWin\Program.cs:行号 66
无 -
-
<wellknown mode="SingleCall" type="MySystem.impl" objectUri="Aimpl.rem"/>
<wellknown mode="SingleCall" type="MySystem.impl" objectUri="Bimpl.rem"/>
<wellknown mode="SingleCall" type="MySystem.impl" objectUri="Cimpl.rem"/>
这个配置项目在客户端和服务器都有吧~ 是一样的吗?
我的思路就是,既然能够通过读取配置项来运行程序,那么这些配置项也可以通过硬编码来提供,而不一定非要从文件读取.
那么服务器和客户端都可以通过硬编码激活,而不用从配置项文件读取.
-
// 服务器端改动 void Application_Start(object sender, EventArgs e) { //在应用程序启动时运行的代码 HttpChannel channel = new HttpChannel(9090); ChannelServices.RegisterChannel(channel, false); //RegisterWellKnownServiceType中第一个参数使用实现类的类型。 string strUrl = "service1_0/test.rem"; RemotingConfiguration.RegisterWellKnownServiceType(typeof(impl.TestImpl), strUrl, WellKnownObjectMode.SingleCall); } // 客户端改动 static void Main(string[] args) { string strUrl = "http://localhost:9090/service1_0/test.rem"; // Activator 第一个参数也需要使用实现类的类型。 ITest service = (ITest)Activator.GetObject(typeof(TestImpl), strUrl); int x = service.Add(10, 20); Console.WriteLine(x); Console.ReadKey(); }
-
我用 HttpChannel channel = new HttpChannel(9090); 指定了 9090 端口,也就是基址是 http://localhost:9090
然后我注册的相对地址是 string strUrl = "service1_0/test.rem";
客户端调用时,要访问的地址是:http://localhost:9090/service1_0/test.rem;
和配置虚拟目录无关.
我在VS中调试通过,先启动Web项目,然后启动客户端.
-
项目是IIS宿主的.
我复制你的也没有成功呀,提示:无法连接到远程服务器
区别就是在客户端是不引用IMPL的,只是通过接口来调用.只引用接口层,不引用实现层,我是下面的写法
string strUrl = "http://localhost:9090/service1_0/test.rem";
// Activator 第一个参数也需要使用实现类的类型。
ITest service = (ITest)Activator.GetObject(typeof(ITest), strUrl);//这里是ITest,你是TestImpl
int x = service.Add(10, 20);
Console.WriteLine(x);
Console.ReadKey();
无 -
你复制我的代码,按 F5 运行网站项目,然后在IE 中输入 http://localhost:9090/service1_0/test.rem?wsdl
-
<definitions name="TestImpl" targetNamespace="http://schemas.microsoft.com/clr/nsassem/impl/impl%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
−
<message name="TestImpl.AddInput">
<part name="a" type="xsd:int"/>
<part name="b" type="xsd:int"/>
</message>
−
<message name="TestImpl.AddOutput">
<part name="return" type="xsd:int"/>
</message>
−
<portType name="TestImplPortType">
−
<operation name="Add" parameterOrder="a b">
<input name="AddRequest" message="tns:TestImpl.AddInput"/>
<output name="AddResponse" message="tns:TestImpl.AddOutput"/>
</operation>
</portType>
−
<binding name="TestImplBinding" type="tns:TestImplPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
−
<suds:class type="ns0:TestImpl" rootType="MarshalByRefObject">
<suds:implements type="ns2:ITest"/>
</suds:class>
−
<operation name="Add">
<soap:operation soapAction="http://schemas.microsoft.com/clr/nsassem/impl.TestImpl/impl#Add"/>
<suds:method attributes="public virtual"/>
−
<input name="AddRequest">
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://schemas.microsoft.com/clr/nsassem/impl.TestImpl/impl"/>
</input>
−
<output name="AddResponse">
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://schemas.microsoft.com/clr/nsassem/impl.TestImpl/impl"/>
</output>
</operation>
</binding>
−
<message name="ITest.AddInput">
<part name="a" type="xsd:int"/>
<part name="b" type="xsd:int"/>
</message>
−
<message name="ITest.AddOutput">
<part name="return" type="xsd:int"/>
</message>
−
<portType name="ITestPortType">
−
<operation name="Add" parameterOrder="a b">
<input name="AddRequest" message="tns:ITest.AddInput"/>
<output name="AddResponse" message="tns:ITest.AddOutput"/>
</operation>
</portType>
−
<binding name="ITestBinding" type="tns:ITestPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<suds:interface type="ns2:ITest">
</suds:interface>
−
<operation name="Add">
<soap:operation soapAction="http://schemas.microsoft.com/clr/nsassem/Interface.ITest/Interface#Add"/>
−
<input name="AddRequest">
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://schemas.microsoft.com/clr/nsassem/Interface.ITest/Interface"/>
</input>
−
<output name="AddResponse">
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://schemas.microsoft.com/clr/nsassem/Interface.ITest/Interface"/>
</output>
</operation>
</binding>
−
<service name="TestImplService">
−
<port name="TestImplPort" binding="tns:TestImplBinding">
<soap:address location="http://localhost:9090/service1_0/test.rem"/>
</port>
</service>
</definitions>
无 -
-
在解决方案中,把网站的虚拟路径设置为:/service1_0,端口号设置为:1678
服务器端只注册:
void Application_Start(object sender, EventArgs e) { string strUrl = "test.rem"; RemotingConfiguration.RegisterWellKnownServiceType(typeof(impl.TestImpl), strUrl, WellKnownObjectMode.SingleCall); }
启动调试,在IE输入:http://localhost:1678/service1_0/test.rem?wsdl
这下可以符合IIS的模式.
-
大哥,麻烦你告诉我,你是在VS中调试测试的结果,还是在IIS中测试的结果?
http://localhost/service1_0/test.rem?wsdl
该路径等价于:
http://localhost:80/service1_0/test.rem?wsdl
如果在VS中调试的话,把网站的虚拟路径设置为:/service1_0,端口号设置为:80,
然后你就可以用这个地址访问了 http://localhost/service1_0/test.rem?wsdl