C#将typeof(x)传递给一个函数(例如lHost = new ServiceHost(typeof(Tester1));)

时间:2015-12-12 00:10:16

标签: c# wcf .net-4.5 servicehost

我在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多个互联网页面的建议),但我似乎无法让它发挥作用。

非常感谢任何帮助。

1 个答案:

答案 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( );