【问题标题】:Declaratively configure WCF behavior extension on programmatically constructed endpoint在以编程方式构造的端点上以声明方式配置 WCF 行为扩展
【发布时间】:2012-05-01 05:19:31
【问题描述】:

我有一个想要添加到 WCF 客户端的 WCF 行为扩展。但是,客户端是以编程方式构建的。端点地址可能会有所不同,但我知道类型。我可以通过编程方式或在配置文件中添加行为(首选),但我只需要在配置文件中传递一些配置。

我不希望在常见行为 (machine.config) 中出现这种情况。

我可以通过编程方式添加行为

endpoint.Behaviors.Add(new MyCustomBehavior())

但我宁愿在配置中进行,所以我也可以在那里配置扩展。

是否可以以声明方式向仅知道类型或接口的以编程方式构造的端点添加和配置端点行为扩展,同时让客户端以编程方式构造?

<system.serviceModel>
  <client>
    <!-- Created programmatically -->
  </client>
<extensions>
  <behaviorExtensions>
    <add name="MyCustomBehavior" type="namespace.CustomBehaviors", MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </behaviorExtensions>   
</extensions>
  <behaviors>
    <endpointBehaviors>
      <behavior name="MyCustomBehavior">
        <MyCustomBehavior MyImportantBehaviorParam1="foo"  />
      </behavior>
    </endpointBehaviors>   
  </behaviors>
</system.serviceModel>

当然,我可以将配置放在另一个部分,并在那里读取我的行为,但如果可能的话,我宁愿使用 WCF 工具。

【问题讨论】:

    标签: wcf app-config endpointbehavior


    【解决方案1】:

    为此,您需要为您的端点创建一个行为配置扩展。有关如何执行此操作的更多信息,请查看https://docs.microsoft.com/en-us/archive/blogs/carlosfigueira/wcf-extensibility-behavior-configuration-extensions

    更新:我现在看到了您的问题。没有直接的方法可以将配置中声明的行为添加到通过代码创建的端点。不过,您仍然可以这样做,但是您需要使用一些反射来访问行为配置扩展的 CreateBehavior 方法(该方法受保护)以实际创建端点行为,以将其添加到通过代码创建的端点.下面的代码展示了如何做到这一点。

    public class StackOverflow_10232385
    {
        public class MyCustomBehavior : IEndpointBehavior
        {
            public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
                Console.WriteLine("In {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name);
            }
    
            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                Console.WriteLine("In {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name);
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
                Console.WriteLine("In {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name);
            }
    
            public void Validate(ServiceEndpoint endpoint)
            {
                Console.WriteLine("In {0}.{1}", this.GetType().Name, MethodBase.GetCurrentMethod().Name);
            }
        }
    
        public class MyCustomBehaviorExtension : BehaviorExtensionElement
        {
            public override Type BehaviorType
            {
                get { return typeof(MyCustomBehavior); }
            }
    
            protected override object CreateBehavior()
            {
                return new MyCustomBehavior();
            }
        }
    
        [ServiceContract]
        public interface ITest
        {
            [OperationContract]
            string Echo(string text);
        }
        public class Service : ITest
        {
            public string Echo(string text)
            {
                return text;
            }
        }
    
        public static void Test()
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
            ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
    
            var configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ServiceModelSectionGroup smsg = configuration.GetSectionGroup("system.serviceModel") as ServiceModelSectionGroup;
            EndpointBehaviorElement endpointBehaviorElement = smsg.Behaviors.EndpointBehaviors["MyCustomBehavior_10232385"];
            foreach (BehaviorExtensionElement behaviorElement in endpointBehaviorElement)
            {
                MethodInfo createBehaviorMethod = behaviorElement.GetType().GetMethod("CreateBehavior", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null);
                IEndpointBehavior behavior = createBehaviorMethod.Invoke(behaviorElement, new object[0]) as IEndpointBehavior;
                endpoint.Behaviors.Add(behavior);
            }
    
            host.Open();
            Console.WriteLine("Host opened");
    
            ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
            ITest proxy = factory.CreateChannel();
            Console.WriteLine(proxy.Echo("Hello"));
    
            ((IClientChannel)proxy).Close();
            factory.Close();
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }
    

    以及这段代码的配置:

    <system.serviceModel>
        <extensions>
            <behaviorExtensions>
                <add name="myCustomBehavior_10232385" type="QuickCode1.StackOverflow_10232385+MyCustomBehaviorExtension, QuickCode1"/>
            </behaviorExtensions>
        </extensions>
        <behaviors>
            <endpointBehaviors>
                <behavior name="MyCustomBehavior_10232385">
                    <myCustomBehavior_10232385/>
                </behavior>
            </endpointBehaviors>
        </behaviors>
    </system.serviceModel>
    

    【讨论】:

    • 我的行为已经实现了行为扩展,请注意 中的参数...抱歉,如果我的问题不清楚,但在我能找到的所有示例中,behaviourConfiguration 都以声明方式添加到构造的端点(服务或客户端)。我需要知道如何将它添加到具有以编程方式创建的给定合同的端点。
    • 明白了,之前没看懂。我已经用这个更新了答案,你可以在github.com/carlosfigueira/WCFQuickSamples/tree/master/WCFForums/…找到完整的代码。
    • 感谢您努力提供该解决方法!我已经放弃了做我想做的事情,转而选择更简单的事情,但是如果我重新访问该项目,您的代码将非常有帮助!
    猜你喜欢
    • 2017-04-09
    • 1970-01-01
    • 2012-02-07
    • 2010-11-03
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多