Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize dynamic compilation and WS Service invocation of .NET

2025-02-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "how to realize the dynamic compilation and WS service invocation of .NET". The content of the explanation in this article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "how to realize the dynamic compilation and WS service invocation of .NET".

First of all, dynamic compilation is very simple in .NET, actually involving only two types: CodeDomProvider and CompilerParameters, both of which are in the System.CodeDom.Compiler namespace.

The following code dynamically compiles the source code into an assembly:

Dynamic compilation

The copy code is as follows:

CodeDomProvider provider = CodeDomProvider.CreateProvider ("CSharp")

CompilerParameters codeParameters = new CompilerParameters ()

CodeParameters.GenerateExecutable = false; / / compiled to dll, if true compiled to exe

CodeParameters.GenerateInMemory = true; / / the compiled assembly is saved to memory

StringBuilder code = new StringBuilder ()

/ / construct the source code here

CompilerResults results = provider.CompileAssemblyFromSource (codeParameters, code.ToString ())

Assembly assembly = null; / / dynamically compiled generated assemblies

If (! results.Errors.HasErrors)

{

Assembly = results.CompiledAssembly

}

After we get the assembly, we can then get the type in the assembly through reflection, then instantiate it, and call the type method.

But before we do that, we have to construct a proxy class for the WS service. What does it look like? Using the WCF framework, it is also very simple to create a service proxy class. The common proxy class structure is as follows:

Service invocation proxy class

The copy code is as follows:

[ServiceContract (Namespace= "https://www.jb51.net/")])

Public interface TestService

{

[OperationContract (Action = "https://www.jb51.net/HelloWorld", ReplyAction =" https://www.jb51.net/HelloWorldResponse")]

String HelloWorld ()

}

Public class TestServiceClient: ClientBase, TestService

{

Public TestServiceClient (Binding binding, EndpointAddress address):

Base (binding, address)

{

}

Public string HelloWorld ()

{

Return base.Channel.HelloWorld ()

}

}

So, if we want to dynamically construct the source code of the proxy class, we should know the namespace of the service, the Action address of the service method, the ReplyAction address, and of course, the name of the service method, the return type, and the parameter list. Here, we omit the parameter list of the service method and construct the proxy class, which is actually a problem of string assembly. First, we create a type to hold the parameters used to construct the proxy class:

Service proxy class construction parameters

The copy code is as follows:

Public class WebServiceParamaters

{

Public string address

Public string Address

{

Get {return address;}

Set

{

Address = value

}

}

Private string serviceNamespace

Public string ServiceNamespace

{

Get {return serviceNamespace;}

Set

{

ServiceNamespace = value

}

}

Private string methodAction

Public string MethodAction

{

Get {return methodAction;}

Set

{

MethodAction = value

}

}

Private string methodReplyAction

Public string MethodReplyAction

{

Get {return methodReplyAction;}

Set

{

MethodReplyAction = value

}

}

Private string methodName

Public string MethodName

{

Get {return methodName;}

Set

{

MethodName = value

}

}

Private string returnType

Public string ReturnType

{

Get {return returnType;}

Set

{

ReturnType = value

}

}

}

Okay, now we just need to construct the proxy class source code, then dynamically compile the assembly of the proxy class, and finally invoke the service method through reflection:

WebServiceProxyCreator

The copy code is as follows:

Public class WebServiceProxyCreator

{

Public Object WebServiceCaller (WebServiceParamaters parameters)

{

CodeDomProvider provider = CodeDomProvider.CreateProvider ("CSharp")

CompilerParameters codeParameters = new CompilerParameters ()

CodeParameters.GenerateExecutable = false

CodeParameters.GenerateInMemory = true

StringBuilder code = new StringBuilder ()

CreateProxyCode (code, parameters)

CodeParameters.ReferencedAssemblies.Add ("System.dll")

CodeParameters.ReferencedAssemblies.Add ("System.ServiceModel.dll")

CompilerResults results = provider.CompileAssemblyFromSource (codeParameters, code.ToString ())

Assembly assembly = null

If (! results.Errors.HasErrors)

{

Assembly = results.CompiledAssembly

}

Type clientType = assembly.GetType ("RuntimeServiceClient")

ConstructorInfo ci = clientType.GetConstructor (new Type [] {typeof (Binding), typeof (EndpointAddress)})

BasicHttpBinding binding = new BasicHttpBinding (); / / only demonstrate traditional WebService calls

EndpointAddress address = new EndpointAddress (parameters.address)

Object client = ci.Invoke (new object [] {binding, address})

MethodInfo mi = clientType.GetMethod (parameters.MethodName)

Object result = mi.Invoke (client, null)

Mi = clientType.GetMethod ("Close"); / / close the agent

Mi.Invoke (client, null)

Return result

}

Public static void CreateProxyCode (StringBuilder code, WebServiceParamaters parameters)

{

Code.AppendLine ("using System;")

Code.AppendLine ("using System.ServiceModel;")

Code.AppendLine ("using System.ServiceModel.Channels;")

Code.Append (@ "[ServiceContract ("))

If (! String.IsNullOrEmpty (parameters.ServiceNamespace))

{

Code.Append ("Namespace=\") .append (parameters.ServiceNamespace) .append ("\")

}

Code.AppendLine (")]")

Code.AppendLine ("public interface IRuntimeService")

Code.AppendLine ("{")

Code.Append ("[OperationContract ("))

If (! String.IsNullOrEmpty (parameters.MethodAction))

{

Code.Append ("Action=\") .append (parameters.MethodAction) .append ("\")

If (! String.IsNullOrEmpty (parameters.MethodReplyAction))

{

Code.Append (,)

}

}

If (! String.IsNullOrEmpty (parameters.MethodReplyAction))

{

Code.Append ("ReplyAction=\") .append (parameters.MethodReplyAction) .append ("\")

}

Code.AppendLine (")]")

Code.Append (parameters.ReturnType) .append ("")

Code.Append (parameters.MethodName) .AppendLine ("();")

Code.AppendLine ("}")

Code.AppendLine ()

Code.AppendLine ("public class RuntimeServiceClient: ClientBase, IRuntimeService")

Code.AppendLine ("{")

Code.AppendLine ("public RuntimeServiceClient (Binding binding, EndpointAddress address): base (binding, address)")

Code.AppendLine ("{")

Code.AppendLine ("}")

Code.Append ("public") .append (parameters.ReturnType) .append ("")

Code.Append (parameters.MethodName) .AppendLine ("()")

Code.AppendLine ("{")

Code.Append ("return base.Channel.") .append (parameters.MethodName) .AppendLine ("();")

Code.AppendLine ("}")

Code.AppendLine ("}")

}

}

Note that in the red part, because the proxy class uses the WCF framework, we need to add a reference to System.ServiceModel when compiling. Of course, System.dll must be necessary. Note here that System.ServiceModel.dll should be saved to the application directory, otherwise an exception will be thrown during dynamic compilation. It is simple to add a reference to System.ServiceModel in the project reference, and then set the copy to the local property to true in the property.

At this point, we can invoke the service directly through the passed-in service address, service method name, and related namespace (although we can only call no-parameter services, and although we can only invoke services that use BasicHttpBinding binding, the reason for these restrictions is... I am lazy, well, I believe these restrictions can be removed with a little change.

Unfortunately, our program is still stupid: every time the service is called, it needs to generate code, compile, create a proxy instance and finally call, um... Then cache it:

Override the GetHashCode method in the WebServiceParameters class:

The copy code is as follows:

Public override int GetHashCode ()

{

Return String.Concat (serviceNamespace, methodAction, methodReplyAction, methodName, returnType). GetHashCode ()

}

Then add the caching mechanism to WebServiceProxyCreator:

The copy code is as follows:

Public class WebServiceProxyCreator

{

Private static Dictionary proxyTypeCatch = new Dictionary ()

Public Object WebServiceCaller (WebServiceParamaters parameters)

{

Int key = parameters.GetHashCode ()

Type clientType = null

If (proxyTypeCatch.ContainsKey (key))

{

ClientType = proxyTypeCatch [key]

Debug.WriteLine ("use cache")

}

Else

{

CodeDomProvider provider = CodeDomProvider.CreateProvider ("CSharp")

CompilerParameters codeParameters = new CompilerParameters ()

CodeParameters.GenerateExecutable = false

CodeParameters.GenerateInMemory = true

StringBuilder code = new StringBuilder ()

CreateProxyCode (code, parameters)

CodeParameters.ReferencedAssemblies.Add ("System.dll")

CodeParameters.ReferencedAssemblies.Add ("System.ServiceModel.dll")

CompilerResults results = provider.CompileAssemblyFromSource (codeParameters, code.ToString ())

Assembly assembly = null

If (! results.Errors.HasErrors)

{

Assembly = results.CompiledAssembly

}

ClientType = assembly.GetType ("RuntimeServiceClient")

ProxyTypeCatch.Add (key, clientType)

}

ConstructorInfo ci = clientType.GetConstructor (new Type [] {typeof (Binding), typeof (EndpointAddress)})

BasicHttpBinding binding = new BasicHttpBinding (); / / only demonstrate traditional WebService calls

EndpointAddress address = new EndpointAddress (parameters.address)

Object client = ci.Invoke (new object [] {binding, address})

MethodInfo mi = clientType.GetMethod (parameters.MethodName)

Object result = mi.Invoke (client, null)

Mi = clientType.GetMethod ("Close"); / / close the agent

Mi.Invoke (client, null)

Return result

}

}

Thank you for your reading, the above is the content of "how to achieve the dynamic compilation of .NET and WS service invocation". After the study of this article, I believe you have a deeper understanding of how to achieve the dynamic compilation of .NET and WS service invocation, and the specific usage needs to be verified by practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report