首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用反射的Wcf动态主机

使用反射的Wcf动态主机
EN

Stack Overflow用户
提问于 2012-10-23 23:56:34
回答 1查看 2.9K关注 0票数 4

我的目标是创建一个能够解析多个程序集、检测契约和托管服务的宿主应用程序。

为了加载服务,我们通常需要对servicehost实例化进行硬编码。下面的代码虽然不是我想要的行为,但仍然可以正常工作。

代码语言:javascript
复制
ServiceHost wService1Host = new ServiceHost(typeof(Service1));
wService1Host.Open();

ServiceHost wService2Host = new ServiceHost(typeof(Service2));
wService2Host.Open();

然而,这意味着我提前知道了服务是什么。我不介意引用包含服务的程序集。我只希望宿主不知道程序集中包含了什么服务。例如,如果我向其中一个程序集添加一个新服务,则不需要在主机端进行任何更改。

这与这个question非常相似,但是由于上面提到的原因而增加了复杂性。

这是我到目前为止附带的主机代码。目前我并不介意管理这些服务,我只是希望它们能够正确加载。

代码语言:javascript
复制
class Program
  {
    static void Main(string[] args)
    {

      // find currently executing assembly
      Assembly curr = Assembly.GetExecutingAssembly();

      // get the directory where this app is running in
      string currentLocation = Path.GetDirectoryName(curr.Location);

      // find all assemblies inside that directory
      string[] assemblies = Directory.GetFiles(currentLocation, "*.dll");

      // enumerate over those assemblies
      foreach (string assemblyName in assemblies)
      {
        // load assembly just for inspection
        Assembly assemblyToInspect = Assembly.ReflectionOnlyLoadFrom(assemblyName);

        // I've hardcoded the name of the assembly containing the services only to ease debugging
        if (assemblyToInspect != null && assemblyToInspect.GetName().Name == "WcfServices")
        {
          // find all types
          Type[] types = assemblyToInspect.GetTypes();

          // enumerate types and determine if this assembly contains any types of interest
          // you could e.g. put a "marker" interface on those (service implementation)
          // types of interest, or you could use a specific naming convention (all types
          // like "SomeThingOrAnotherService" - ending in "Service" - are your services)
          // or some kind of a lookup table (e.g. the list of types you need to find from
          // parsing the app.config file)
          foreach (Type ty in types)
          {
            Assembly implementationAssembly = Assembly.GetAssembly(ty);
            // When loading the type for the service, load it from the implementing assembly.
            Type implementation = implementationAssembly.GetType(ty.FullName);

            ServiceHost wServiceHost = new ServiceHost(implementation); // FAIL
            wServiceHost.Open();
          }
        }
      }
      Console.WriteLine("Service are up and running.");
      Console.WriteLine("Press <Enter> to stop services...");
      Console.ReadLine();
    }
  }

尝试创建serviceHost时出现以下错误:

代码语言:javascript
复制
"It is illegal to reflect on the custom attributes of a Type loaded via ReflectionOnlyGetType (see Assembly.ReflectionOnly) -- use CustomAttributeData instead."

在上面给出的链接中,这个家伙似乎已经使用typeof解决了它的问题,因为他提前知道他想要公开什么服务。不幸的是,这不是我的案子。

注意:对于托管部分,我实际上有3个项目。第一个是主机应用程序(见上),第二个是包含所有服务契约(接口)的程序集,最后一个程序集包含服务实现。

这是我实际用于托管服务的app.config。包含实现的程序集名为"WcfServices“,包含2个服务。一种是公开回调,另一种只公开基本服务。

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>    
    <behaviors>
      <serviceBehaviors>  
        <behavior name="metadataBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>        
      </serviceBehaviors>  
    </behaviors>
    <services>
      <service name="WcfServices.Service1"
               behaviorConfiguration="metadataBehavior">

        <endpoint address="Service1Service"
                  binding="basicHttpBinding"
                  contract="WcfServices.IService1"
                  name="basicHttp"/>

        <endpoint binding="mexHttpBinding"
                  contract="IMetadataExchange"
                  name="metadataExchange"/>

        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/Service1"/>
          </baseAddresses>
        </host>        
      </service>

      <service name="WcfServices.Service2"
               behaviorConfiguration="metadataBehavior">

        <endpoint address="Service2Service"
                  binding="wsDualHttpBinding"
                  contract="WcfServices.IService2"/>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange"/>

        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/Service2"/>
          </baseAddresses>
        </host>
      </service>

    </services>    
  </system.serviceModel>
</configuration>

所以,需要明确的是,这是我要找的:

  1. 在当前应用程序directory
  2. Looks中加载程序集如果其中有任何协定实现
  3. 如果有,则实例化这些服务(暂时使用app.config )

首先,这有可能吗?(我的猜测是,因为一个名为wcfstorm alread的应用程序似乎可以做到这一点)

显然,我怎样才能让上面的代码工作呢?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-25 03:16:30

这就是我最终要做的:

代码语言:javascript
复制
private static void LoadServices()
{
  // find currently executing assembly
  Assembly Wcurr = Assembly.GetExecutingAssembly();

  // get the directory where this app is running in
  string wCurrentLocation = Path.GetDirectoryName(Wcurr.Location);

  // enumerate over those assemblies
  foreach (string wAssemblyName in mAssemblies)
  {
    // load assembly just for inspection
    Assembly wAssemblyToInspect = null;
    try
    {
      wAssemblyToInspect = Assembly.LoadFrom(wCurrentLocation + "\\" + wAssemblyName);
    }
    catch (System.Exception ex)
    {
      Console.WriteLine("Unable to load assembly : {0}", wAssemblyName);
    }


    if (wAssemblyToInspect != null)
    {
      // find all types with the HostService attribute
      IEnumerable<Type> wTypes = wAssemblyToInspect.GetTypes().Where(t => Attribute.IsDefined(t, typeof(HostService), false));

      foreach (Type wType in wTypes)
      {
        ServiceHost wServiceHost = new ServiceHost(wType);
        wServiceHost.Open();
        mServices.Add(wServiceHost);
        Console.WriteLine("New Service Hosted : {0}", wType.Name);
      }
    }
  }

  Console.WriteLine("Services are up and running.");
}

注意:这种方法要求程序集被“宿主”项目引用。

Note2 :为了加速程序集解析,我在"mAssemblies“中硬编码了哪些程序集要加载。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13034546

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档