static void FillOperationsForInterface(ContractDescription cd, Type exactContractType, Type givenServiceType, bool isCallback) { // FIXME: load Behaviors MethodInfo [] contractMethods = /*exactContractType.IsInterface ? GetAllMethods (exactContractType) :*/ exactContractType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); MethodInfo [] serviceMethods = contractMethods; if (givenServiceType != null && exactContractType.IsInterface) { var l = new List <MethodInfo> (); foreach (Type t in GetAllInterfaceTypes(exactContractType)) { l.AddRange(givenServiceType.GetInterfaceMap(t).TargetMethods); } serviceMethods = l.ToArray(); } for (int i = 0; i < contractMethods.Length; ++i) { MethodInfo mi = contractMethods [i]; OperationContractAttribute oca = GetOperationContractAttribute(mi); if (oca == null) { continue; } MethodInfo end = null; if (oca.AsyncPattern) { if (String.Compare("Begin", 0, mi.Name, 0, 5) != 0) { throw new InvalidOperationException("For async operation contract patterns, the initiator method name must start with 'Begin'."); } string endName = "End" + mi.Name.Substring(5); end = mi.DeclaringType.GetMethod(endName); if (end == null) { throw new InvalidOperationException(String.Format("'{0}' method is missing. For async operation contract patterns, corresponding End method is required for each Begin method.", endName)); } if (GetOperationContractAttribute(end) != null) { throw new InvalidOperationException("Async 'End' method must not have OperationContractAttribute. It is automatically treated as the EndMethod of the corresponding 'Begin' method."); } } OperationDescription od = GetOrCreateOperation(cd, mi, serviceMethods [i], oca, end != null ? end.ReturnType : null, isCallback); if (end != null) { od.EndMethod = end; } } }
internal static OperationContractAttribute GetOperationContractAttribute(MethodInfo method) { OperationContractAttribute operationContractAttribute = GetSingleAttribute <OperationContractAttribute>(method); if (operationContractAttribute != null) { return(operationContractAttribute); } IOperationContractAttributeProvider operationContractProvider = GetFirstAttribute <IOperationContractAttributeProvider>(method); if (operationContractProvider != null) { return(operationContractProvider.GetOperationContractAttribute()); } return(null); }
private static string GetOperationAction(OperationContractAttribute operationContractAttribute, MethodInfo methodInfo) { if (!operationContractAttribute.Action.IsNullOrEmpty()) { return(operationContractAttribute.Action); } var sca = typeof(TContract).GetCustomAttributes(typeof(ServiceContractAttribute), false) .Cast <ServiceContractAttribute>() .Single(); var serviceName = sca.Name ?? typeof(TContract).Name; var operationName = operationContractAttribute.AsyncPattern ? methodInfo.Name.Substring("Begin".Length) : methodInfo.Name; // http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.action.aspx return(string.Format("{0}/{1}/{2}", sca.Namespace, serviceName, operationName)); }
private static string GetOperationAction(OperationContractAttribute operationContractAttribute, MethodInfo methodInfo) { if (!operationContractAttribute.Action.IsNullOrEmpty()) { return(operationContractAttribute.Action); } var sca = typeof(TContract).GetCustomAttributes(typeof(ServiceContractAttribute), false) .Cast <ServiceContractAttribute>() .Single(); var serviceName = sca.Name ?? typeof(TContract).Name; var operationName = operationContractAttribute.AsyncPattern ? methodInfo.Name.Substring("Begin".Length) : methodInfo.Name; // https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.operationcontractattribute.action return($"{sca.Namespace}/{serviceName}/{operationName}"); }
internal static void VerifyOneway(Type interfaceType) { Debug.Assert(interfaceType.IsInterface); MethodInfo[] methods = interfaceType.GetMethods(); foreach (MethodInfo method in methods) { object[] attributes = method.GetCustomAttributes(typeof(OperationContractAttribute), true); Debug.Assert(attributes.Length == 1); OperationContractAttribute attribute = attributes[0] as OperationContractAttribute; if (attribute.IsOneWay == false) { throw new InvalidOperationException("All operations on contract " + interfaceType + " must be one-way, but operation " + method.Name + " is not configured for one-way"); } } }
public override IMessage Invoke(IMessage msg) { IMethodCallMessage methodCall = (IMethodCallMessage)msg; //得到操作名称 object[] attributes = methodCall.MethodBase.GetCustomAttributes(typeof(OperationContractAttribute), true); OperationContractAttribute attribute = (OperationContractAttribute)attributes[0]; string operationName = string.IsNullOrEmpty(attribute.Name) ? methodCall.MethodName : attribute.Name; //序列化请求消息 Message requestMessage = this.MessageFormatters[operationName].SerializeRequest(this.MessageVersion, methodCall.InArgs); //添加必要的WS-Address报头 EndpointAddress address = new EndpointAddress(this.Address); requestMessage.Headers.MessageId = new UniqueId(Guid.NewGuid()); requestMessage.Headers.ReplyTo = new EndpointAddress("http://www.w3.org/2005/08/addressing/anonymous"); address.ApplyTo(requestMessage); //对请求消息进行编码,并将编码生成的字节发送通过HttpWebRequest向服务端发送 HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(this.Address); webRequest.Method = "Post"; webRequest.KeepAlive = true; webRequest.ContentType = "application/soap+xml; charset=utf-8"; ArraySegment <byte> bytes = this.MessageEncoderFactory.Encoder.WriteMessage(requestMessage, int.MaxValue, BufferManager.CreateBufferManager(long.MaxValue, int.MaxValue)); webRequest.ContentLength = bytes.Array.Length; webRequest.GetRequestStream().Write(bytes.Array, 0, bytes.Array.Length); webRequest.GetRequestStream().Close(); WebResponse webResponse = webRequest.GetResponse(); //对HttpResponse进行解码生成回复消息. Message responseMessage = this.MessageEncoderFactory.Encoder.ReadMessage(webResponse.GetResponseStream(), int.MaxValue); //回复消息进行反列化生成相应的对象,并映射为方法调用的返回值或者ref/out参数 object[] allArgs = (object[])Array.CreateInstance(typeof(object), methodCall.ArgCount); Array.Copy(methodCall.Args, allArgs, methodCall.ArgCount); object[] refOutParameters = new object[GetRefOutParameterCount(methodCall.MethodBase)]; object returnValue = this.MessageFormatters[operationName].DeserializeReply(responseMessage, refOutParameters); MapRefOutParameter(methodCall.MethodBase, allArgs, refOutParameters); //通过ReturnMessage的形式将返回值和ref/out参数返回 return(new ReturnMessage(returnValue, allArgs, allArgs.Length, methodCall.LogicalCallContext, methodCall)); }
/// <summary> /// This method wrapps an instance call /// </summary> /// <param name="methodInfo">The method to call</param> /// <param name="arrMethodArgs">The arguments to the method call</param> public object DoMethodCall(object[] arrMethodArgs, MethodInfo methodInfo) { ParameterInfo[] pis = methodInfo.GetParameters(); if ((arrMethodArgs.Length != pis.Length)) { throw new ArgumentException("Arguments count not match!"); } var proxy = ServiceProxy.GetProxy(_serviceName); Parameter[] paras = new Parameter[arrMethodArgs.Length]; List <int> outParas = new List <int>(); for (int i = 0; i < pis.Length; i++) { var pi = pis[i]; if (pi.IsOut || pi.ParameterType.IsByRef) { paras[i] = new Parameter(arrMethodArgs[i], pi.ParameterType.GetElementType(), Com.Bj58.Spat.Gaea.Client.Proxy.Enum.ParaType.Out); outParas.Add(i); } else { paras[i] = new Parameter(arrMethodArgs[i], pi.ParameterType, Com.Bj58.Spat.Gaea.Client.Proxy.Enum.ParaType.In); } } string methodName = methodInfo.Name; var atts = methodInfo.GetCustomAttributes(typeof(Com.Bj58.Spat.Gaea.OperationContractAttribute), true); if (atts != null && atts.Length > 0) { OperationContractAttribute ma = (OperationContractAttribute)atts[0]; if (!string.IsNullOrEmpty(ma.Name)) { methodName = ma.Name; } methodName = "$" + methodName; } var result = proxy.Invoke(methodInfo.ReturnType, _type, methodName, paras); for (int i = 0; i < outParas.Count && i < result.OutPara.Length; i++) { arrMethodArgs[outParas[i]] = result.OutPara[i]; } return(result.Result); }
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); }
static Uri GetOperationInfo(MethodInfo operation, Uri baseAddress, out string method, out WebInvokeAttribute webinvoke, out OperationContractAttribute operationcontract, out WebMessageFormat requestformat, out WebMessageFormat responseformat) { object[] customAttributes = operation.GetCustomAttributes(false); webinvoke = customAttributes.Single(a => a is WebInvokeAttribute) as WebInvokeAttribute; method = webinvoke.Method; operationcontract = customAttributes.Single(a => a is OperationContractAttribute) as OperationContractAttribute; requestformat = webinvoke.RequestFormat; responseformat = webinvoke.ResponseFormat; Uri relative = new Uri(webinvoke.UriTemplate, UriKind.Relative); Uri endpoint = new Uri(baseAddress, relative); return(endpoint); }
public void TestReplyActionGeneration() { ProjectMappingManagerSetup.InitializeManager(ServiceProvider, "ProjectMapping.ServiceContractDsl.Tests.xml"); ServiceContract rootElement = CreateRoot(ServiceContractElementName, ServiceContractElementNamespace); Operation op1 = new Operation(Store); WCFOperationContract oc = new WCFOperationContract(); oc.ReplyAction = "foo"; op1.ObjectExtender = oc; op1.Name = "op1"; op1.ServiceContract = rootElement; string content = RunTemplate(rootElement); Type generatedType = CompileAndGetType(content); MethodInfo method = TypeAsserter.AssertMethod(op1.Name, generatedType); OperationContractAttribute operation = TypeAsserter.AssertAttribute <OperationContractAttribute>(method); Assert.AreEqual <string>(oc.ReplyAction, operation.ReplyAction); }
public void TestProperUnwrappingOfSoapFaults() { ServiceDescription serviceDescription = new ServiceDescription(typeof(IServiceWithMessageContract)); ContractDescription contractDescription = new ContractDescription(serviceDescription, typeof(IServiceWithMessageContract), new ServiceContractAttribute()); System.Reflection.MethodInfo method = typeof(IServiceWithMessageContract).GetMethod(nameof(IServiceWithMessageContract.ThrowTypedFault)); OperationContractAttribute contractAttribute = new OperationContractAttribute(); ServiceModel.OperationDescription operationDescription = new ServiceModel.OperationDescription(contractDescription, method, contractAttribute); var faultInfo = Assert.Single(operationDescription.Faults); Assert.Equal("TypedSoapFault", faultInfo.Name); var properties = faultInfo.GetProperties().Where(prop => prop.CustomAttributes.All(attr => attr.AttributeType.Name != "IgnoreDataMemberAttribute")); var faultProperty = Assert.Single(properties); Assert.Equal("MyIncludedProperty", faultProperty.Name); }
public void UsesExistingOperationContractAttributeWithDecoratedMethod() { se.ObjectName = "UsesExistingOperationContractAttributeWithDecoratedMethod"; se.TargetName = "decoratedService"; 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 oca = attrs[0] as OperationContractAttribute; Assert.AreEqual("MySomeMethod", oca.Name); }
public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg) { IMethodCallMessage methodCall = (IMethodCallMessage)msg; //得到操作名称 object[] attributes = methodCall.MethodBase.GetCustomAttributes(typeof(OperationContractAttribute), false); OperationContractAttribute attribute = attributes[0] as OperationContractAttribute; string operationName = string.IsNullOrEmpty(attribute.Name) ? methodCall.MethodName : attribute.Name; Message requestMessage = MessageFormatter[operationName].SerializeRequest(this.MessageVersion, methodCall.InArgs); EndpointAddress address = new EndpointAddress(this.Address); requestMessage.Headers.MessageId = new UniqueId(Guid.NewGuid()); requestMessage.Headers.ReplyTo = new EndpointAddress("http://www.w3.org/2005/08/addressing/anonymous"); address.ApplyTo(requestMessage); HttpWebRequest web = (HttpWebRequest)HttpWebRequest.Create(Address); web.Method = "Post"; web.KeepAlive = true; web.ContentType = "application/soap+xml; charset=utf-8"; ArraySegment <byte> bytes = this.MessageEncoderFactory.Encoder.WriteMessage(requestMessage, int.MaxValue, BufferManager.CreateBufferManager(long.MaxValue, int.MaxValue)); web.ContentLength = bytes.Array.Length; web.GetRequestStream().Write(bytes.Array, 0, bytes.Array.Length); web.GetRequestStream().Close(); WebResponse response = (WebResponse)web.GetResponse(); //回复消息进行反列化生成相应的对象,并映射为方法调用的返回值或者ref/out参数 object[] allArgs = (object[])Array.CreateInstance(typeof(object), methodCall.ArgCount); Array.Copy(methodCall.Args, allArgs, methodCall.ArgCount); Message responseMessage = this.MessageEncoderFactory.Encoder.ReadMessage(response.GetResponseStream(), int.MaxValue); object result = this.MessageFormatter[operationName].DeserializeReply(responseMessage, new object[GetRefOutParamterCount(methodCall.MethodBase)]); MapRefOutParameter(methodCall.MethodBase, allArgs, new object[GetRefOutParamterCount(methodCall.MethodBase)]); return(new ReturnMessage(result, allArgs, allArgs.Length, methodCall.LogicalCallContext, methodCall)); }
public List <string> GetOperationsList() { List <string> operations = new List <string>(); Type contractType = GetContractType(); foreach (MethodInfo method in contractType.GetMethods()) { object[] testAttributes = method.GetCustomAttributes(typeof(OperationContractAttribute), true); if (testAttributes.Length > 0) { OperationContractAttribute attr = (OperationContractAttribute)testAttributes[0]; if (!string.IsNullOrEmpty(attr.Action)) { operations.Add(method.Name); } } } return(operations); }
public void ShouldGetDefaultActionValue() { ProjectMappingManagerSetup.InitializeManager(ServiceProvider, "ProjectMapping.ServiceContractDsl.Tests.xml"); ServiceContract rootElement = CreateRoot(ServiceContractElementName, ServiceContractElementNamespace); Operation op1 = new Operation(Store); op1.ServiceContract = rootElement; op1.ObjectExtender = new WCFOperationContract(); op1.Name = "op1"; // commit the tx and trigger the OperationAddRule so the action value will be filled with the default value this.transaction.Commit(); this.transaction = null; string content = RunTemplate(rootElement); Type generatedType = CompileAndGetType(content); MethodInfo method = TypeAsserter.AssertMethod(op1.Name, generatedType); OperationContractAttribute operation = TypeAsserter.AssertAttribute <OperationContractAttribute>(method); Assert.AreEqual <string>(rootElement.Namespace + "/" + rootElement.Name + "/" + op1.Name, operation.Action); }
public OperationDescription(ContractDescription contract, MethodInfo operationMethod, MethodInfo implementingMethod, OperationContractAttribute contractAttribute) { Contract = contract; Name = contractAttribute.Name ?? operationMethod.Name; SoapAction = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{contract.Name}/{Name}"; IsOneWay = contractAttribute.IsOneWay; IsMessageContractResponse = operationMethod .ReturnType .CustomAttributes .FirstOrDefault(ca => ca.AttributeType == typeof(MessageContractAttribute)) != null; ReplyAction = contractAttribute.ReplyAction; DispatchMethod = operationMethod; ImplementingMethod = implementingMethod; AllParameters = operationMethod.GetParameters() .Select((info, index) => CreateParameterInfo(info, index, contract)) .ToArray(); InParameters = AllParameters .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.OutOnlyRef) .ToArray(); OutParameters = AllParameters .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.InOnly) .ToArray(); IsMessageContractRequest = InParameters.Length == 1 && InParameters.First().Parameter.ParameterType .CustomAttributes .FirstOrDefault(ca => ca.AttributeType == typeof(MessageContractAttribute)) != null; ReturnName = operationMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? Name + "Result"; }
private static OperationContractAttribute ConvertFromServiceModelOperationContractAttribute(object attr) { Fx.Assert(attr.GetType().FullName.Equals(ServiceReflector.SMOperationContractAttributeFullName), "Expected attribute of type S.SM.OperationContractAttribute"); bool hasProtectionLevel = GetProperty <bool>(attr, "HasProtectionLevel"); if (hasProtectionLevel) { // ProtectionLevel isn't supported yet so if it was set on the S.SM.SCA, then we can't do the mapping so throw throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new PlatformNotSupportedException("System.ServiceModel.OperationContractAttribute.ProtectionLevel")); } var oca = new OperationContractAttribute(); string tmpStr = GetProperty <string>(attr, nameof(OperationContractAttribute.Name)); if (!string.IsNullOrEmpty(tmpStr)) { oca.Name = tmpStr; } tmpStr = GetProperty <string>(attr, nameof(OperationContractAttribute.Action)); if (tmpStr != null) // String.Empty apparently is fine { oca.Action = tmpStr; } tmpStr = GetProperty <string>(attr, nameof(OperationContractAttribute.ReplyAction)); if (tmpStr != null) // String.Empty apparently is fine { oca.ReplyAction = tmpStr; } oca.AsyncPattern = GetProperty <bool>(attr, nameof(OperationContractAttribute.AsyncPattern)); oca.IsOneWay = GetProperty <bool>(attr, nameof(OperationContractAttribute.IsOneWay)); // TODO: IsInitiating and IsTerminating return(oca); }
object ProcessMessage(AMFMessage amfMessage) { // Apply AMF-based operation selector /* * Dictionary<string, string> operationNameDictionary = new Dictionary<string, string>(); * foreach (OperationDescription operation in _endpoint.Contract.Operations) * { * try * { * operationNameDictionary.Add(operation.Name.ToLower(), operation.Name); * } * catch (ArgumentException) * { * throw new Exception(String.Format("The specified contract cannot be used with case insensitive URI dispatch because there is more than one operation named {0}", operation.Name)); * } * } */ //SessionMode, CallbackContract, ProtectionLevel AMFMessage output = new AMFMessage(amfMessage.Version); for (int i = 0; i < amfMessage.BodyCount; i++) { AMFBody amfBody = amfMessage.GetBodyAt(i); object content = amfBody.Content; if (content is IList) { content = (content as IList)[0]; } IMessage message = content as IMessage; if (message != null) { //WCF should not assign client id for Flex... if (message.clientId == null) { message.clientId = Guid.NewGuid().ToString("D"); } //IMessage resultMessage = _endpoint.ServiceMessage(message); IMessage responseMessage = null; CommandMessage commandMessage = message as CommandMessage; if (commandMessage != null && commandMessage.operation == CommandMessage.ClientPingOperation) { responseMessage = new AcknowledgeMessage(); responseMessage.body = true; } else { RemotingMessage remotingMessage = message as RemotingMessage; string operation = remotingMessage.operation; //TODO: you could use an alias for a contract to expose a different name to the clients in the metadata using the Name property of the ServiceContract attribute string source = remotingMessage.source; Type serviceType = TypeHelper.Locate(source); Type contractInterface = serviceType.GetInterface(_endpoint.Contract.ContractType.FullName); //WCF also lets you apply the ServiceContract attribute directly on the service class. Avoid using it. //ServiceContractAttribute serviceContractAttribute = ReflectionUtils.GetAttribute(typeof(ServiceContractAttribute), type, true) as ServiceContractAttribute; if (contractInterface != null) { object instance = Activator.CreateInstance(serviceType); IList parameterList = remotingMessage.body as IList; MethodInfo mi = MethodHandler.GetMethod(contractInterface, operation, parameterList, false, false); //MethodInfo mi = MethodHandler.GetMethod(serviceType, operation, parameterList, false, false); if (mi != null) { //TODO OperationContract attribute to alias it to a different publicly exposed name OperationContractAttribute operationContractAttribute = ReflectionUtils.GetAttribute(typeof(OperationContractAttribute), mi, true) as OperationContractAttribute; if (operationContractAttribute != null) { //mi = MethodHandler.GetMethod(serviceType, operation, parameterList, false, false); ParameterInfo[] parameterInfos = mi.GetParameters(); object[] args = new object[parameterInfos.Length]; parameterList.CopyTo(args, 0); TypeHelper.NarrowValues(args, parameterInfos); object result = mi.Invoke(instance, args); if (!(result is IMessage)) { responseMessage = new AcknowledgeMessage(); responseMessage.body = result; } else { responseMessage = result as IMessage; } } else { responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException("Method in not part of an service contract")); } } else { responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException("Method in not part of an service contract")); } } else { responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException(String.Format("The specified contract {0} cannot be used with the source named {1} and operation named {2}", _endpoint.Contract.ContractType.Name, source, operation))); } } if (responseMessage is AsyncMessage) { ((AsyncMessage)responseMessage).correlationId = message.messageId; } responseMessage.destination = message.destination; responseMessage.clientId = message.clientId; ResponseBody responseBody = new ResponseBody(amfBody, responseMessage); output.AddBody(responseBody); } } return(output); }
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 internal XmlName GetOperationName(MethodInfo method) { OperationContractAttribute operationAttribute = GetOperationContractAttribute(method); return(NamingHelper.GetOperationName(GetLogicalName(method), operationAttribute.Name)); }
public OperationDescriptor(string action, string name, string ns, MethodInfo method, OperationContractAttribute contract, ServiceContractAttribute serviceContract) { Action = action; Name = name; Namespace = ns; Method = method; Contract = contract; ServiceContract = serviceContract; }
private static void CheckInvalidMethodDeclaration(Type contractInterface, List <MethodComparator> methods) { foreach (MethodInfo m in contractInterface.GetMethods()) { { OperationContractAttribute ocAnnotation = TypeHelper.GetAttribute <OperationContractAttribute>(m); if (ocAnnotation != null) { // 4. szabály ellenőrzése if (!m.ReturnType.Equals(typeof(Stream)) && typeof(Stream).IsAssignableFrom(m.ReturnType)) { throw new InvalidContractDefinitionException(String.Format("Return type '{0}' of the method '{1}' of contract '{2}' is not allowed. Use the base class instead.", m.ReturnType.FullName, m.Name, contractInterface.Name)); } if (m.GetParameters().Length > 0) { foreach (ParameterInfo pt in m.GetParameters()) { if (!pt.ParameterType.Equals(typeof(Stream)) && typeof(Stream).IsAssignableFrom(pt.ParameterType)) { throw new InvalidContractDefinitionException(String.Format("Parameter type '{0}' of the method '{1}' of contract '{2}' is not allowed. Use the base class instead.", pt.ParameterType.FullName, m.Name, contractInterface.Name)); } } } // 5. szabály ellenőrzése if (ocAnnotation.IsOneWay && !m.ReturnType.Equals(typeof(void))) { throw new InvalidContractDefinitionException(String.Format("Return type '{0}' of the method '{1}' of contract '{2}' is not allowed for OneWay mode.", m.ReturnType.FullName, m.Name, contractInterface.Name)); } // 6. szabály ellenőrzése if (!ocAnnotation.IsOneWay && !ocAnnotation.IsReliable) { throw new InvalidContractDefinitionException(String.Format("Invalid reliable mode setting for method '{0}' of the contract type '{1}'. Non reliable communication allowed only for OneWay mode.", m.Name, contractInterface.Name)); } } // 7. szabály ellenőrzése MethodComparator cmp = new MethodComparator(m); if (methods.Contains(cmp)) { MethodComparator otherCmp = null; foreach (MethodComparator mc in methods) { if (mc.Equals(cmp)) { otherCmp = mc; break; } } OperationContractAttribute otherOcAnnotation = TypeHelper.GetAttribute <OperationContractAttribute>(otherCmp.Method); if (ocAnnotation == null && otherOcAnnotation == null) { // do nothing } else if (ocAnnotation != null && otherOcAnnotation != null) { if (ocAnnotation.Direction != otherOcAnnotation.Direction) { throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Setting 'direction' is different.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName)); } if (ocAnnotation.IsOneWay != otherOcAnnotation.IsOneWay) { throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Setting 'isOneWay' is different.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName)); } if (ocAnnotation.IsReliable != otherOcAnnotation.IsReliable) { throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Setting 'isReliable' is different.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName)); } if (ocAnnotation.CallTimeout != otherOcAnnotation.CallTimeout) { throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Setting 'timeout' is different.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName)); } } else { // az egyiken van annotáció, a másikon meg nincs throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Same {4} must be exist on methods.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName, typeof(OperationContractAttribute).Name)); } } else { methods.Add(cmp); } } } }
public OperationDescription(ContractDescription contract, MethodInfo operationMethod, OperationContractAttribute contractAttribute) { Contract = contract; Name = contractAttribute.Name ?? GetNameByAction(contractAttribute.Action) ?? operationMethod.Name; SoapAction = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{contract.Name}/{Name}"; IsOneWay = contractAttribute.IsOneWay; ReplyAction = contractAttribute.ReplyAction; DispatchMethod = operationMethod; var returnType = operationMethod.ReturnType; if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task <>)) { returnType = returnType.GenericTypeArguments[0]; } IsMessageContractResponse = returnType.CustomAttributes .FirstOrDefault(ca => ca.AttributeType == typeof(MessageContractAttribute)) != null; AllParameters = operationMethod.GetParameters() .Select((info, index) => CreateParameterInfo(info, index, contract)) .ToArray(); InParameters = AllParameters .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.OutOnlyRef) .ToArray(); OutParameters = AllParameters .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.InOnly) .ToArray(); IsMessageContractRequest = InParameters.Length == 1 && InParameters.First().Parameter.ParameterType .CustomAttributes .FirstOrDefault(ca => ca.AttributeType == typeof(MessageContractAttribute)) != null; ReturnName = operationMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? Name + "Result"; var faultContractAttributes = operationMethod.GetCustomAttributes <FaultContractAttribute>(); Faults = faultContractAttributes .Where(a => a.DetailType?.Name != null) .Select(a => a.DetailType) .ToArray(); }
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); } } 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); }
public OperationDescription(ContractDescription contract, MethodInfo operationMethod, OperationContractAttribute contractAttribute) { Contract = contract; Name = contractAttribute.Name ?? operationMethod.Name; SoapAction = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{Name}"; IsOneWay = contractAttribute.IsOneWay; ReplyAction = contractAttribute.ReplyAction; DispatchMethod = operationMethod; }
static ContractDescription GetContract(Type givenContractType, Type givenServiceType, bool assumeServiceContract) { // FIXME: serviceType should be used for specifying attributes like OperationBehavior. Type exactContractType = null; ServiceContractAttribute sca = null; Dictionary <Type, ServiceContractAttribute> contracts = GetServiceContractAttributes(givenServiceType ?? givenContractType); if (contracts.ContainsKey(givenContractType)) { exactContractType = givenContractType; sca = contracts[givenContractType]; } else { foreach (Type t in contracts.Keys) { if (t.IsAssignableFrom(givenContractType)) { if (t.IsAssignableFrom(exactContractType)) // exact = IDerived, t = IBase { continue; } if (sca != null && (exactContractType == null || !exactContractType.IsAssignableFrom(t))) // t = IDerived, exact = IBase { throw new InvalidOperationException("The contract type of " + givenContractType + " is ambiguous: can be either " + exactContractType + " or " + t); } exactContractType = t; sca = contracts [t]; } } } if (exactContractType == null) { exactContractType = givenContractType; } if (sca == null) { if (assumeServiceContract) { sca = new ServiceContractAttribute(); } else { throw new InvalidOperationException(String.Format("Attempted to get contract type from '{0}' which neither is a service contract nor does it inherit service contract.", givenContractType)); } } string name = sca.Name ?? exactContractType.Name; string ns = sca.Namespace ?? "http://tempuri.org/"; ContractDescription cd = new ContractDescription(name, ns); cd.ContractType = exactContractType; cd.CallbackContractType = sca.CallbackContract; cd.SessionMode = sca.SessionMode; if (sca.ConfigurationName != null) { cd.ConfigurationName = sca.ConfigurationName; } else { cd.ConfigurationName = exactContractType.FullName; } if (sca.HasProtectionLevel) { cd.ProtectionLevel = sca.ProtectionLevel; } // FIXME: load Behaviors MethodInfo [] contractMethods = exactContractType.IsInterface ? GetAllMethods(exactContractType) : exactContractType.GetMethods(); MethodInfo [] serviceMethods = contractMethods; if (givenServiceType != null && exactContractType.IsInterface) { var l = new List <MethodInfo> (); foreach (Type t in GetAllInterfaceTypes(exactContractType)) { l.AddRange(givenServiceType.GetInterfaceMap(t).TargetMethods); } serviceMethods = l.ToArray(); } for (int i = 0; i < contractMethods.Length; ++i) { MethodInfo mi = contractMethods [i]; OperationContractAttribute oca = GetOperationContractAttribute(mi); if (oca == null) { continue; } MethodInfo end = null; if (oca.AsyncPattern) { if (String.Compare("Begin", 0, mi.Name, 0, 5) != 0) { throw new InvalidOperationException("For async operation contract patterns, the initiator method name must start with 'Begin'."); } string endName = "End" + mi.Name.Substring(5); end = mi.DeclaringType.GetMethod(endName); if (end == null) { throw new InvalidOperationException(String.Format("'{0}' method is missing. For async operation contract patterns, corresponding End method is required for each Begin method.", endName)); } if (GetOperationContractAttribute(end) != null) { throw new InvalidOperationException("Async 'End' method must not have OperationContractAttribute. It is automatically treated as the EndMethod of the corresponding 'Begin' method."); } } OperationDescription od = GetOrCreateOperation(cd, mi, serviceMethods [i], oca, end != null ? end.ReturnType : null); if (end != null) { od.EndMethod = end; } } // FIXME: enable this when I found where this check is needed. /* * if (cd.Operations.Count == 0) * throw new InvalidOperationException (String.Format ("The service contract type {0} has no operation. At least one operation must exist.", contractType)); */ return(cd); }
public OperationDescription(ContractDescription contract, MethodInfo operationMethod, OperationContractAttribute contractAttribute) { Contract = contract; Name = contractAttribute.Name ?? operationMethod.Name; SoapAction = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{contract.Name}/{Name}"; IsOneWay = contractAttribute.IsOneWay; ReplyAction = contractAttribute.ReplyAction; DispatchMethod = operationMethod; NormalParameters = operationMethod.GetParameters().Where(x => !x.IsOut && !x.ParameterType.IsByRef) .Select(info => CreateParameterInfo(info, contract)).ToArray(); OutParameters = operationMethod.GetParameters().Where(x => x.IsOut || x.ParameterType.IsByRef) .Select(info => CreateParameterInfo(info, contract)).ToArray(); ReturnName = operationMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? Name + "Result"; }
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"); } MessageDescription md; if (mca != null) { md = CreateMessageDescription(messageType, cd.Namespace, action, isRequest, isCallback, mca); } else { md = CreateMessageDescription(oca, plist, od.Name, cd.Namespace, action, isRequest, isCallback, retType); } // ReturnValue if (!isRequest) { MessagePartDescription mp = CreatePartCore(GetMessageParameterAttribute(mi.ReturnTypeCustomAttributes), od.Name + "Result", md.Body.WrapperNamespace); mp.Index = 0; mp.Type = mca != null ? typeof(void) : retType; md.Body.ReturnValue = mp; } return(md); }
static OperationDescription GetOrCreateOperation( ContractDescription cd, MethodInfo mi, MethodInfo serviceMethod, OperationContractAttribute oca, Type asyncReturnType, bool isCallback, Type givenServiceType) { string name = oca.Name ?? (oca.AsyncPattern ? mi.Name.Substring(5) : mi.Name); OperationDescription od = cd.Operations.FirstOrDefault(o => o.Name == name && o.InCallbackContract == isCallback); if (od == null) { od = new OperationDescription(name, cd); od.IsOneWay = oca.IsOneWay; if (oca.HasProtectionLevel) { od.ProtectionLevel = oca.ProtectionLevel; } if (HasInvalidMessageContract(mi, oca.AsyncPattern)) { throw new InvalidOperationException(String.Format("The operation {0} contains more than one parameters and one or more of them are marked with MessageContractAttribute, but the attribute must be used within an operation that has only one parameter.", od.Name)); } #if !MOONLIGHT var xfa = serviceMethod.GetCustomAttribute <XmlSerializerFormatAttribute> (false); if (xfa != null) { od.Behaviors.Add(new XmlSerializerOperationBehavior(od, xfa)); } #endif var dfa = serviceMethod.GetCustomAttribute <DataContractFormatAttribute> (false); if (dfa != null) { od.Behaviors.Add(new DataContractSerializerOperationBehavior(od, dfa)); } od.Messages.Add(GetMessage(od, mi, oca, true, isCallback, null)); if (!od.IsOneWay) { var md = GetMessage(od, mi, oca, false, isCallback, asyncReturnType); od.Messages.Add(md); var mpa = mi.ReturnParameter.GetCustomAttribute <MessageParameterAttribute> (true); if (mpa != null) { var mpd = md.Body.Parts.FirstOrDefault(pd => pd.Name == mpa.Name); if (mpd != null) { md.Body.Parts.Remove(mpd); md.Body.ReturnValue = mpd; mpd.Name = mpa.Name; } else if (md.Body.ReturnValue == null) { throw new InvalidOperationException(String.Format("Specified message part '{0}' in MessageParameterAttribute on the return value, was not found", mpa.Name)); } } } var knownTypeAtts = cd.ContractType.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), false).Union( mi.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), false)).Union( serviceMethod.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), false)); foreach (ServiceKnownTypeAttribute a in knownTypeAtts) { foreach (Type t in a.GetTypes(givenServiceType)) { 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) && od.InCallbackContract == isCallback) { 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); }
public OperationDescription(ContractDescription contract, MethodInfo operationMethod, OperationContractAttribute contractAttribute) { Contract = contract; Name = contractAttribute.Name ?? operationMethod.Name; SoapAction = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{contract.Name}/{Name}"; IsOneWay = contractAttribute.IsOneWay; ReplyAction = contractAttribute.ReplyAction; DispatchMethod = operationMethod; AllParameters = operationMethod.GetParameters() .Select((info, index) => CreateParameterInfo(info, index, contract)) .ToArray(); InParameters = AllParameters .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.OutOnlyRef) .ToArray(); OutParameters = AllParameters .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.InOnly) .ToArray(); ReturnName = operationMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? Name + "Result"; }