操作带有所需参数的合同 [英] OperationContract with required parameters

查看:66
本文介绍了操作带有所需参数的合同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如约翰·桑德斯(John Saunders)(MVP)所建议的那样,我以不同的方式重新发布了我原来的问题/问题/增强请求.已经开始使用我们的WCF服务(通过wsHttpBinding/basicHttpBinding公开)的客户抱怨:为什么在大多数情况下,所有服务中的所有参数实际上都不是可选的?"例如,假设有一个这样的服务:

As suggested by John Saunders (MVP), I'm reposting my original problem/question/enhancement-request in a different way. Our customers who have started using our WCF services (exposed via wsHttpBinding/basicHttpBinding) complain, "Why are all parameters in all of your services declared as optional when most of the times they really aren't?" For example, let's say there is a service like this:


推荐答案

至少对于简单参数,可以使用IParameterInspector强制它们存在(请参见下文).该解决方案有两个局限性:它不会更改WSDL(仍然会注意到参数是可选的),并且不适用于可空类型.要使用可空类型,实际上需要一个新的格式化程序(基本上是自己对不同参数进行反序列化).

At least for simple parameters, you can use an IParameterInspector to enforce that they are present (see below). This solution has two limitations: it doesn't change the WSDL (which will still note the parameters are optional), and it doesn't work for nullable types. To work for nullable types you'd actually need a new formatter (basically doing the deserialization of the different parameters yourself).

    public class Post_e707ed20_c09c_4e26_927a_7c3071d74ed7
    {
        [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
        public class RequiredDataParameterAttribute : Attribute { }

        [ServiceContract]
        public interface ITest
        {
            [OperationContract]
            int Transfer(
                [RequiredDataParameter] int SourceAccount,
                [RequiredDataParameter] int TargetAccount,
                [RequiredDataParameter] double Amount);
        }
        [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
        public class Service : ITest
        {
            public int Transfer(int SourceAccount, int TargetAccount, double Amount)
            {
                return 1;
            }
        }
        class MyParamInspector : IParameterInspector
        {
            private bool[] required;
            private string[] paramNames;
            public MyParamInspector(OperationDescription operationDescription)
            {
                MethodInfo method = operationDescription.SyncMethod;
                ParameterInfo[] parameters = method.GetParameters();
                this.required = new bool[parameters.Length];
                this.paramNames = new string[parameters.Length];
                for (int i = 0; i < this.required.Length; i++)
                {
                    this.paramNames[i] = parameters[i].Name;
                    object[] attrs = parameters[i].GetCustomAttributes(typeof(RequiredDataParameterAttribute), true);
                    this.required[i] = attrs != null && attrs.Length > 0;
                }
            }
            public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
            {
            }

            public object BeforeCall(string operationName, object[] inputs)
            {
                Debug.Assert(this.required.Length == inputs.Length);
                for (int i = 0; i < this.required.Length; i++)
                {
                    if (this.required[i] && inputs[i] == null)
                    {
                        throw new ArgumentException("Required parameter " + this.paramNames[i] + " is not present in the request");
                    }
                }
                return null;
            }
        }
        class MyOperationBehavior : IOperationBehavior
        {
            public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { }
            public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { }
            public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
            {
                dispatchOperation.ParameterInspectors.Add(new MyParamInspector(operationDescription));
            }
            public void Validate(OperationDescription operationDescription) { }
        }
        static Binding GetBinding()
        {
            BasicHttpBinding result = new BasicHttpBinding();
            return result;
        }
        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), GetBinding(), "");
            foreach (OperationDescription operation in endpoint.Contract.Operations)
            {
                operation.Behaviors.Add(new MyOperationBehavior());
            }
            host.Open();
            Console.WriteLine("Host opened");

            ChannelFactory<ITest> factory = new ChannelFactory<ITest>(GetBinding(), new EndpointAddress(baseAddress));
            ITest proxy = factory.CreateChannel();
            Console.WriteLine(proxy.Transfer(1, 2, 23.45));

            ((IClientChannel)proxy).Close();
            factory.Close();

            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }


这篇关于操作带有所需参数的合同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆