I'm using C#, .Net Framework 4.5.1 in SharpDevelop.
Is there a way to create a function that accepts "typeof(ISomeInterface)" and "typeof(SomeClass)" as parameters?
Situation: I'm building an application, that is supposed to host several WebServices. Each WebService will be created on it's own System.ServiceModel.ServiceHost. Currently, there are only two WebServices running (Tester1 and Tester2, as I'm just trying to get it to work).
In the future, there will be multiple WebServices running in this application, perhaps even "unknown", but derived from my bases. My current setup works, but, as you can see in the code below, is far from being the most DRY-style code. So, naturally, I would like to move all repeating code into a method.
Currently, I have the following code:
First, I have a base-interface and a base-class:
[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 )
{
}
}
From which I have derived two child interfaces and classes:
[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 );
}
}
At current, the code below creates and runs the WebServices, based on the above interfaces and classes:
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
}
}
As can be seen, the two methods (Run1 and Run2) are about 90% identical, except that they use ITester1 & Tester1 or ITester2 & Tester2.
Now, I have replaced some code:
lHost = new ServiceHost( typeof(Tester1) );
lHost.AddServiceEndpoint( typeof(ITester1), binding, iHTTPUri );
and
lHost = new ServiceHost( typeof(Tester2) );
lHost.AddServiceEndpoint( typeof(ITester2), binding, iHTTPUri );
By some more "generic" code:
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 );
This, in preparation of moving the code to a method. The code still works, and I still get the response (currently, just the WebServices WSDL) I expect.
The obvious next step, would be to move all code in the if( lWhatService == 1 )
and else if( lWhatService == 2 )
blocks to a single method.
I have used several ways, but below is where I currently am:
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;
}
The above code, I would like to call as:
lHost1 = GetHost<ITester1, Tester1>( "localhost", 80, "Tester1", "wsdl" );
lHost1.Open( );
lHost2 = GetHost<ITester2, Tester2>( "localhost", 80, "Tester2", "wsdl" );
lHost2.Open( );
The code works, in the sense that I do not get any compile-time or run-time errors. I also get a response from the application. However, in my previous way (coding both WebServices completely) I got the WSDL-XML as a response. In the current way (calling a method) I get and empty page (not an error, just a blanc page).
I have also tried these before:
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 );
....
}
Calling them like:
lHost = GetHost( "localhost", 80, typeof(ITester1), typeof(Tester1), "Tester1", "wsdl" );
and
lHost = GetHost( "localhost", 80, ITester1, Tester1, "Tester1", "wsdl" );
But that got me an empty page just the same.
Is there any way to get the above work, so I can call it either as:
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" );
I have tried these and about 9 more variations (suggestion from over 20 internet pages), but I just cannot seem to get this to work.
Any help would be greatly appreciated.