static bool WebAttributesOCEExtender (MethodBase method, object[] customAttributes, ref OperationContractAttribute oca)
		{
			int caLength = customAttributes == null ? 0 : customAttributes.Length;
			if (method == null && caLength == 0)
				return false;

			if (caLength == 0) {
				customAttributes = method.GetCustomAttributes (false);

				if (customAttributes.Length == 0)
					return false;
			}

			bool foundWebAttribute = false;
			foreach (object o in customAttributes) {
				if (o is WebInvokeAttribute || o is WebGetAttribute) {
					foundWebAttribute = true;
					break;
				}
			}

			if (!foundWebAttribute)
				return false;

			// LAMESPEC: .NET allows for contract methods decorated only with
			// Web{Get,Invoke}Attribute and _without_ the OperationContractAttribute.
			if (oca == null)
				oca = new OperationContractAttribute ();
			
			return true;
		}
        public void CreatesCustomOperationContractAttributeWithNoDecoratedMethod()
        {
            OperationContractAttribute oca1 = new OperationContractAttribute();
            oca1.Name = "MySomeMethod";

            se.ObjectName = "CreatesCustomOperationContractAttributeWithNoDecoratedMethod";
            se.TargetName = "service";
            se.MemberAttributes.Add("SomeMethod", oca1);
            se.AfterPropertiesSet();

            Type proxyType = se.GetObject() as Type;
            Assert.IsNotNull(proxyType);
            MethodInfo method = proxyType.GetMethod("SomeMethod");
            Assert.IsNotNull(method);

            object[] attrs = method.GetCustomAttributes(typeof(OperationContractAttribute), true);
            Assert.IsNotEmpty(attrs);
            Assert.AreEqual(1, attrs.Length);

            OperationContractAttribute oca2 = attrs[0] as OperationContractAttribute;
            Assert.AreEqual(oca1.Name, oca2.Name);
        }
		public static MessageDescription CreateMessageDescription (
			OperationContractAttribute oca, ParameterInfo[] plist, string name, string defaultNamespace, string action, bool isRequest, bool isCallback, Type retType, ICustomAttributeProvider retTypeAttributes)
		{
			var dir = isRequest ^ isCallback ? MessageDirection.Input : MessageDirection.Output;
			MessageDescription md = new MessageDescription (action, dir) { IsRequest = isRequest };

			MessageBodyDescription mb = md.Body;
			mb.WrapperName = name + (isRequest ? String.Empty : "Response");
			mb.WrapperNamespace = defaultNamespace;

			if (oca.HasProtectionLevel)
				md.ProtectionLevel = oca.ProtectionLevel;

			// Parts
			int index = 0;
			foreach (ParameterInfo pi in plist) {
				// AsyncCallback and state are extraneous.
				if (oca.AsyncPattern && pi.Position == plist.Length - 2)
					break;

				// They are ignored:
				// - out parameter in request
				// - neither out nor ref parameter in reply
				if (isRequest && pi.IsOut)
					continue;
				if (!isRequest && !pi.IsOut && !pi.ParameterType.IsByRef)
					continue;

				MessagePartDescription pd = CreatePartCore (GetMessageParameterAttribute (pi), pi.Name, defaultNamespace);
				pd.Index = index++;
				pd.Type = MessageFilterOutByRef (pi.ParameterType);
				mb.Parts.Add (pd);			
			}

			// ReturnValue
			if (!isRequest) {
				MessagePartDescription mp = CreatePartCore (GetMessageParameterAttribute (retTypeAttributes), name + "Result", mb.WrapperNamespace);
				mp.Index = 0;
				mp.Type = retType;
				mb.ReturnValue = mp;
			}

			// FIXME: fill properties.

			return md;
		}
		static MessageDescription GetMessage (
			OperationDescription od, MethodInfo mi,
			OperationContractAttribute oca, bool isRequest,
			bool isCallback, Type asyncReturnType)
		{
			ContractDescription cd = od.DeclaringContract;
			ParameterInfo [] plist = mi.GetParameters ();
			Type messageType = null;
			string action = isRequest ? oca.Action : oca.ReplyAction;
			MessageContractAttribute mca;

			Type retType = asyncReturnType;
			if (!isRequest && retType == null)
				retType =  mi.ReturnType;

			// If the argument is only one and has [MessageContract]
			// then infer it as a typed messsage
			if (isRequest) {
				int len = mi.Name.StartsWith ("Begin", StringComparison.Ordinal) ? 3 : 1;
				mca = plist.Length != len ? null :
					GetMessageContractAttribute (plist [0].ParameterType);
				if (mca != null)
					messageType = plist [0].ParameterType;
			}
			else {
				mca = GetMessageContractAttribute (retType);
				if (mca != null)
					messageType = retType;
			}

			if (action == null)
				action = String.Concat (cd.Namespace, 
					cd.Namespace.Length == 0 ? "urn:" : cd.Namespace.EndsWith ("/") ? "" : "/", cd.Name, "/",
					od.Name, isRequest ? String.Empty : "Response");

			if (mca != null)
				return CreateMessageDescription (messageType, cd.Namespace, action, isRequest, isCallback, mca);
			return CreateMessageDescription (oca, plist, od.Name, cd.Namespace, action, isRequest, isCallback, retType, mi.ReturnTypeCustomAttributes);
		}
		static OperationDescription GetOrCreateOperation (
			ContractDescription cd, MethodInfo mi, MethodInfo serviceMethod,
			OperationContractAttribute oca,
			Type asyncReturnType,
			bool isCallback)
		{
			string name = oca.Name ?? (oca.AsyncPattern ? mi.Name.Substring (5) : mi.Name);

			OperationDescription od = cd.Operations.FirstOrDefault (o => o.Name == name);
			if (od == null) {
				od = new OperationDescription (name, cd);
				od.IsOneWay = oca.IsOneWay;
				if (oca.HasProtectionLevel)
					od.ProtectionLevel = oca.ProtectionLevel;
				od.Messages.Add (GetMessage (od, mi, oca, true, isCallback, null));
				if (!od.IsOneWay)
					od.Messages.Add (GetMessage (od, mi, oca, false, isCallback, asyncReturnType));
				foreach (ServiceKnownTypeAttribute a in cd.ContractType.GetCustomAttributes (typeof (ServiceKnownTypeAttribute), false))
					foreach (Type t in a.GetTypes ())
						od.KnownTypes.Add (t);
				foreach (ServiceKnownTypeAttribute a in serviceMethod.GetCustomAttributes (typeof (ServiceKnownTypeAttribute), false))
					foreach (Type t in a.GetTypes ())
						od.KnownTypes.Add (t);
				foreach (FaultContractAttribute a in mi.GetCustomAttributes (typeof (FaultContractAttribute), false)) {
					var fname = a.Name ?? a.DetailType.Name + "Fault";
					var fns = a.Namespace ?? cd.Namespace;
					var fd = new FaultDescription (a.Action ?? cd.Namespace + cd.Name + "/" + od.Name + fname) { DetailType = a.DetailType, Name = fname, Namespace = fns };
#if !NET_2_1
					if (a.HasProtectionLevel)
						fd.ProtectionLevel = a.ProtectionLevel;
#endif
					od.Faults.Add (fd);
				}
				cd.Operations.Add (od);
			}
			else if (oca.AsyncPattern && od.BeginMethod != null && od.BeginMethod != mi ||
				 !oca.AsyncPattern && od.SyncMethod != null && od.SyncMethod != mi)
				throw new InvalidOperationException (String.Format ("contract '{1}' cannot have two operations for '{0}' that have the identical names and different set of parameters.", name, cd.Name));

			if (oca.AsyncPattern)
				od.BeginMethod = mi;
			else
				od.SyncMethod = mi;
			od.IsInitiating = oca.IsInitiating;
			od.IsTerminating = oca.IsTerminating;

			if (mi != serviceMethod)
				foreach (object obj in mi.GetCustomAttributes (typeof (IOperationBehavior), true))
					od.Behaviors.Add ((IOperationBehavior) obj);

			if (serviceMethod != null) {
				foreach (object obj in serviceMethod.GetCustomAttributes (typeof(IOperationBehavior),true))
					od.Behaviors.Add ((IOperationBehavior) obj);
			}
#if !NET_2_1
			if (od.Behaviors.Find<OperationBehaviorAttribute>() == null)
				od.Behaviors.Add (new OperationBehaviorAttribute ());
#endif
			// FIXME: fill KnownTypes, Behaviors and Faults.

			if (isCallback)
				od.InCallbackContract = true;
			else
				od.InOrdinalContract = true;

			return od;
		}
        internal ContractMethodInfo(ContractType declaringType, OperationInfo operationInfo)
        {
            if (declaringType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("declaringType");
            }
            if (operationInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operationInfo");
            }
            if (string.IsNullOrEmpty(operationInfo.Name))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("operationInfo",
                    SR2.GetString(SR2.Error_OperationNameNotSpecified));
            }

            this.declaringType = declaringType;
            this.name = operationInfo.Name;
            this.methodAttributes = MethodAttributes.Public |
                MethodAttributes.Abstract |
                MethodAttributes.Virtual;

            SortedList<int, ContractMethodParameterInfo> localParameters =
                new SortedList<int, ContractMethodParameterInfo>();

            foreach (OperationParameterInfo operationParameterInfo in operationInfo.Parameters)
            {
                ContractMethodParameterInfo parameterInfo =
                    new ContractMethodParameterInfo(this, operationParameterInfo);
                if (parameterInfo.Position == -1)
                {
                    this.returnParam = parameterInfo;
                }
                else
                {
                    localParameters.Add(parameterInfo.Position, parameterInfo);
                }
            }

            this.parameters = new ParameterInfo[localParameters.Count];
            foreach (ContractMethodParameterInfo paramInfo in localParameters.Values)
            {
                this.parameters[paramInfo.Position] = paramInfo;
            }

            if (this.returnParam == null)
            {
                OperationParameterInfo returnParameterInfo = new OperationParameterInfo();
                returnParameterInfo.Position = -1;
                returnParameterInfo.ParameterType = typeof(void);

                this.returnParam = new ContractMethodParameterInfo(this, returnParameterInfo);
            }

            OperationContractAttribute operationContract = new OperationContractAttribute();
            if (operationInfo.HasProtectionLevel && operationInfo.ProtectionLevel != null)
            {
                operationContract.ProtectionLevel = (ProtectionLevel) operationInfo.ProtectionLevel;
            }
            operationContract.IsOneWay = operationInfo.IsOneWay;

            this.attributes = new Attribute[] { operationContract };

            declaringType.AddMethod(this);
        }
		static OperationDescription GetOrCreateOperation (
			ContractDescription cd, MethodInfo mi, MethodInfo serviceMethod,
			OperationContractAttribute oca,
			Type asyncReturnType)
		{
			string name = oca.Name ?? (oca.AsyncPattern ? mi.Name.Substring (5) : mi.Name);

			OperationDescription od = null;
			foreach (OperationDescription iter in cd.Operations) {
				if (iter.Name == name) {
					od = iter;
					break;
				}
			}
			if (od == null) {
				od = new OperationDescription (name, cd);
				od.IsOneWay = oca.IsOneWay;
				if (oca.HasProtectionLevel)
					od.ProtectionLevel = oca.ProtectionLevel;
				od.Messages.Add (GetMessage (od, mi, oca, true, null));
				if (!od.IsOneWay)
					od.Messages.Add (GetMessage (od, mi, oca, false, asyncReturnType));
				foreach (ServiceKnownTypeAttribute a in cd.ContractType.GetCustomAttributes (typeof (ServiceKnownTypeAttribute), false))
					foreach (Type t in a.GetTypes ())
						od.KnownTypes.Add (t);
				foreach (ServiceKnownTypeAttribute a in serviceMethod.GetCustomAttributes (typeof (ServiceKnownTypeAttribute), false))
					foreach (Type t in a.GetTypes ())
						od.KnownTypes.Add (t);
				foreach (FaultContractAttribute a in serviceMethod.GetCustomAttributes (typeof (FaultContractAttribute), false))
					od.Faults.Add (new FaultDescription (a.Action) { DetailType = a.DetailType, Name = a.Name, Namespace = a.Namespace });
				cd.Operations.Add (od);
			}
			else if (oca.AsyncPattern && od.BeginMethod != null ||
				 !oca.AsyncPattern && od.SyncMethod != null)
				throw new InvalidOperationException ("A contract cannot have two operations that have the identical names and different set of parameters.");

			if (oca.AsyncPattern)
				od.BeginMethod = mi;
			else
				od.SyncMethod = mi;
			od.IsInitiating = oca.IsInitiating;
			od.IsTerminating = oca.IsTerminating;

			if (mi != serviceMethod)
				foreach (object obj in mi.GetCustomAttributes (typeof (IOperationBehavior), true))
					od.Behaviors.Add ((IOperationBehavior) obj);

			if (serviceMethod != null) {
				foreach (object obj in serviceMethod.GetCustomAttributes (typeof(IOperationBehavior),true))
					od.Behaviors.Add ((IOperationBehavior) obj);
			}
#if !NET_2_1
			if (od.Behaviors.Find<OperationBehaviorAttribute>() == null)
				od.Behaviors.Add (new OperationBehaviorAttribute ());
#endif
			// FIXME: fill KnownTypes, Behaviors and Faults.

			return od;
		}