我在SharpDevelop中使用C#,。NET Framework 4.5.1。
有没有办法创建一个接受" typeof(ISomeInterface)"和#34; typeof(SomeClass)"作为参数?
情况: 我正在构建一个应该承载多个Web服务的应用程序。每个WebService都将在其自己的System.ServiceModel.ServiceHost上创建。目前,只有两个WebServices在运行(Tester1和Tester2,因为我只是想让它运行起来)。
将来,在这个应用程序中会运行多个WebServices,甚至可能是" unknown",但是从我的基础派生出来。我当前的设置有效,但是,正如您在下面的代码中看到的那样,远不是最干的样式代码。所以,当然,我想将所有重复的代码移动到一个方法中。
目前,我有以下代码:
首先,我有一个基本接口和一个基类:
[ServiceContract]
public interface ITester
{
[OperationContract]
void Test( string pText );
}
public class Tester : System.Web.Services.WebService, ITester
{
public Tester( )
{
}
public virtual void Test( string pText )
{
}
}
我从中派生了两个子接口和类:
[ServiceContract]
public interface ITester1 : ITester
{
}
public class Tester1 : Tester, ITester1
{
public override void Test( String pMessage )
{
Console.WriteLine( "Message received : \n{0}\n", pMessage );
}
}
[ServiceContract]
public interface ITester2 : ITester
{
}
public class Tester2 : Tester, ITester2
{
public Tester2( )
{
}
public override void Test( string pText )
{
Console.WriteLine( "Message received : \n{0}\n", pText );
}
}
目前,以下代码基于上述接口和类创建并运行WebServices:
public class Program
{
public static void Main( )
{
int lWhatService = 1; // Actual Program uses user input.
if( lWhatService == 1 )
{
string iServer = "localhost";
int iPort = 80;
string iService = "Tester1";
string iWDSL = "wsdl";
string iHTTPAddress = "http://" + iServer + ":" + iPort.ToString( ) + "/" + iService;
string iMetaAddress = "http://" + iServer + ":" + iPort.ToString( ) + "/" + iService + "/" + iWDSL;
string iNetTCPAddress = "net.tcp://" + iServer + "/" + iService + "/" + iWDSL;
ServiceHost lHost;
Uri iHTTPUri = new Uri( iHTTPAddress );
BasicHttpBinding binding = new BasicHttpBinding( );
lHost = new ServiceHost( typeof(Tester1) );
lHost.AddServiceEndpoint( typeof(ITester1), binding, iHTTPUri );
ServiceMetadataBehavior metadata = new ServiceMetadataBehavior( );
metadata.HttpGetUrl = new Uri( iMetaAddress );
metadata.HttpGetEnabled = true;
lHost.Description.Behaviors.Add( metadata );
Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding( );
Uri mexAddress = new Uri( iNetTCPAddress );
lHost.AddServiceEndpoint( typeof(IMetadataExchange), mexBinding, mexAddress );
lHost.Open( );
}
else if( lWhatService == 2 )
{
string iServer = "localhost";
int iPort = 80;
string iService = "Tester2";
string iWDSL = "wsdl";
string iHTTPAddress = "http://" + iServer + ":" + iPort.ToString( ) + "/" + iService;
string iMetaAddress = "http://" + iServer + ":" + iPort.ToString( ) + "/" + iService + "/" + iWDSL;
string iNetTCPAddress = "net.tcp://" + iServer + "/" + iService + "/" + iWDSL;
ServiceHost lHost;
Uri iHTTPUri = new Uri( iHTTPAddress );
BasicHttpBinding binding = new BasicHttpBinding( );
lHost = new ServiceHost( typeof(Tester2) );
lHost.AddServiceEndpoint( typeof(ITester2), binding, iHTTPUri );
ServiceMetadataBehavior metadata = new ServiceMetadataBehavior( );
metadata.HttpGetUrl = new Uri( iMetaAddress );
metadata.HttpGetEnabled = true;
lHost.Description.Behaviors.Add( metadata );
Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding( );
Uri mexAddress = new Uri( iNetTCPAddress );
lHost.AddServiceEndpoint( typeof(IMetadataExchange), mexBinding, mexAddress );
lHost.Open( );
}
System.Console.ReadKey( ); // This is where the user normally could switch
}
}
可以看出,两种方法(Run1和Run2)大约90%相同,只是它们使用ITester1& Tester1或ITester2& Tester2。
现在,我已经更换了一些代码:
lHost = new ServiceHost( typeof(Tester1) );
lHost.AddServiceEndpoint( typeof(ITester1), binding, iHTTPUri );
and
lHost = new ServiceHost( typeof(Tester2) );
lHost.AddServiceEndpoint( typeof(ITester2), binding, iHTTPUri );
通过更多"泛型"代码:
Type lObj = typeof(Tester1);
lHost = new ServiceHost( lObj );
Type lInt = typeof(ITester1);
lHost.AddServiceEndpoint( lInt, binding, iHTTPUri );
and
Type lObj = typeof(Tester2);
lHost = new ServiceHost( lObj );
Type lInt = typeof(ITester2);
lHost.AddServiceEndpoint( lInt, binding, iHTTPUri );
这,准备将代码移动到方法中。代码仍然有效,我仍然得到了我期望的响应(目前只是WebServices WSDL)。
显而易见的下一步是将if( lWhatService == 1 )
和else if( lWhatService == 2 )
块中的所有代码移动到单个方法中。
我使用了几种方法,但下面是我现在所处的位置:
public static ServiceHost GetHost<T, U>( string pServer, int pPort, string pService, string pWSDL )
{
string iHTTPAddress = "http://" + pServer + ":" + pPort.ToString( ) + "/" + pService;
string iMetaAddress = "http://" + pServer + ":" + pPort.ToString( ) + "/" + pService + "/" + pWSDL;
string iNetTCPAddress = "net.tcp://" + pServer + "/" + pService + "/" + pWSDL;
Type iInterface = typeof(T);
Type iObject = typeof(U);
ServiceHost iHost = new ServiceHost( iObject );
// HTTP Binding => Create and Prepare
Uri iHTTPUri = new Uri( iHTTPAddress );
BasicHttpBinding iHTTPBinding = new BasicHttpBinding( );
// HTTP Binding => Add to Host
iHost.AddServiceEndpoint( iInterface, iHTTPBinding, iHTTPAddress );
....
....
return iHost;
}
以上代码,我想称之为:
lHost1 = GetHost<ITester1, Tester1>( "localhost", 80, "Tester1", "wsdl" );
lHost1.Open( );
lHost2 = GetHost<ITester2, Tester2>( "localhost", 80, "Tester2", "wsdl" );
lHost2.Open( );
代码工作,从某种意义上说,我没有得到任何编译时或运行时错误。我也从应用程序得到了回复。但是,按照我之前的方式(完全编写WebServices编码),我得到了WSDL-XML作为响应。在当前的方式(调用方法)我得到和空页(不是错误,只是一个空白页)。
我之前也试过这些:
public static ServiceHost GetHost( string pServer, int pPort, Type pInterface, Type pObject, string pService, string pWSDL )
{
Type iInterface = typeof(pInterface);
Type iObject = typeof(pObject);
ServiceHost iHost = new ServiceHost( iObject );
....
}
and
public static ServiceHost GetHost( string pServer, int pPort, Type pInterface, Type pObject, string pService, string pWSDL )
{
Type iInterface = pInterface;
Type iObject = pObject;
ServiceHost iHost = new ServiceHost( iObject );
....
}
将它们称为:
lHost = GetHost( "localhost", 80, typeof(ITester1), typeof(Tester1), "Tester1", "wsdl" );
and
lHost = GetHost( "localhost", 80, ITester1, Tester1, "Tester1", "wsdl" );
但这让我的页面空白了。
有没有办法完成上述工作,所以我可以将其称为:
lHost1 = GetHost<ITester1, Tester1>( "localhost", 80, "Tester1", "wsdl" );
or
lHost1 = GetHost( "localhost", 80, typeof(ITester1), typeof(Tester1), "Tester1", "wsdl" );
or (most preferred)
lHost1 = GetHost( "localhost", 80, ITester1, Tester1, "Tester1", "wsdl" );
我已尝试过这些以及大约9种变体(来自20多个互联网页面的建议),但我似乎无法让它发挥作用。
非常感谢任何帮助。
答案 0 :(得分:1)
找到它,我因为没有早点看到而感到羞愧。我的方法错过了一个重要的路线:iMeta.HttpGetEnabled = true;
有了它,它运行正常。应该在iMeta.HttpGetUrl = iMetaUri;
谢谢:
@cubbr:感谢您再次查看我的代码
@Preston Guillog:谢谢你让我更多地思考我在做什么。
现在最终的功能如下:
public static ServiceHost GetHost( string pServer, int pPort, Type pInterface, Type pObject, string pService, string pWSDL )
{
string iHTTPAddress = "http://" + pServer + ":" + pPort.ToString( ) + "/" + pService;
string iMetaAddress = "http://" + pServer + ":" + pPort.ToString( ) + "/" + pService + "/" + pWSDL;
string iNetTCPAddress = "net.tcp://" + pServer + "/" + pService + "/" + pWSDL;
Type iInterface = pInterface;
Type iObject = pObject;
ServiceHost iHost = new ServiceHost( iObject );
// HTTP Binding => Create and Prepare
Uri iHTTPUri = new Uri( iHTTPAddress );
BasicHttpBinding iHTTPBinding = new BasicHttpBinding( );
// HTTP Binding => Add to Host
iHost.AddServiceEndpoint( iInterface, iHTTPBinding, iHTTPAddress );
// MetaData => Create and Prepare
Uri iMetaUri = new Uri( iMetaAddress );
ServiceMetadataBehavior iMeta = new ServiceMetadataBehavior( );
iMeta.HttpGetUrl = iMetaUri;
iMeta.HttpGetEnabled = true;
// MetaData => Add to Host
iHost.Description.Behaviors.Add( iMeta );
Uri iNetTCPUri = new Uri( iNetTCPAddress );
Binding iNetTCPBinding = MetadataExchangeBindings.CreateMexTcpBinding( );
iHost.AddServiceEndpoint( typeof( IMetadataExchange), iNetTCPBinding, iNetTCPUri );
return iHost;
}
可以像:
一样调用lHost = GetHost( "localhost", 80, typeof(ITester1), typeof(Tester1), "Tester1", "wsdl" );
lHost.Open( );