Verification and generation of build-time code and generation based on project code files

I am looking for a method that allows me to check the generator code and code as part of the build process using Visual Studio 2010 (not express) and MSBuild.

Background check:

I am writing a RESTful web service using WCF Web Api. Inside the class of service that the web service represents, I have to define the endpoint by declaring the parameters additionally as a simple test. When the parameter name inside the endpoint declaration is different from the C # method parameter, I get an error - unfortunately, at runtime when accessing the web service, and not at compile time. So I thought it would be nice to parse the web service class as part of the compilation phase for such flaws, returning an error when something is wrong.

Example:

[WebGet(UriTemplate = "Endpoint/{param1}/{param2}")] public string MyMethod(string param1, string parameter2) { // Accessing the web service now will result in an error, // as there no fitting method-parameter named "param2". } 

I would also like to apply some naming rules, such as GET Methods, which should begin with the word “Get”. I believe that this will help the service to remain more convenient when working with several colleagues.

Background Generation:

I will use this REST web service in several other projects because I need to write to the client to access this service. But I do not want to write a client for each of them, always tuning in with every service change. I would like clients to be created automatically based on web service code files.

Previous approach:

So far, I have been trying to use the T4 template using the DTE interface to parse a code file and verify it or create a client. This worked fine in Visual Studio when saving manually, but the integration of this process during the build process was not effective enough because the Visual Studio host was not available using MSBuild.

Any suggestion is welcome. :)

+4
source share
4 answers

Instead of using DTE or some other means for parsing C # code, you can use reflection (with the Reflection-Only context) to test the assembly after it is compiled. Using reflection is a more reliable solution and probably faster (especially if you use Mono.Cecil for reflection).

For MSBuild integration, I would recommend writing a custom MSBuild task - it is quite simple and more reliable / elegant than writing a command-line utility that is executed by MSBuild.

+2
source

It may be a long shot, but still qualifies as “any offer” :)

You can compile the code and then run the post-build command, which will be the tool you will need to write, which uses reflection to compare the analyzed UriTemplate text with the names of the method parameters, catch errors and output them to MSBuild to receive a pickup. See this link for information on how to output, so MSBuild will put errors in the error list of the visual studio. The post-build tool can then remove compiled assemblies if errors are detected, and thus "mimics" the failed build.

Here's the SO link that leads me to the MSBuild blog too, just for reference.

NTN

+2
source

For the compliance side, FxCop custom rules are likely to be very good.

There are many possibilities for generating client code. If you like the T4 approach, there may be a way to make it work with MSBuild (but you will definitely need to provide more details on what is currently not working). If you still need an alternative, a reflection-based post-build tool is another way to go ...

+2
source

Here is a short, extremely ugly program that you can run on an assembly or group of assemblers (just pass the dlls as arguments) to perform a WebGet UriTemplate check. If you don’t miss anything, it works on its own (and does not fit, respectively, since this is its own unit test).

The program will print the name of the method in which there are no parameters and the names of the missing parameters, and if they are found, a non-zero return code will be returned (the standard for program failure), which makes it suitable as an event after assembly. I do not answer if you have bleeding:

 using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.ServiceModel.Web; namespace ConsoleApplication1 { class Program { static int Main(string[] args) { var failList = new ConcurrentDictionary<MethodInfo, ISet<String>>(); var assembliesToRunOn = (args.Length == 0 ? new[] {Assembly.GetExecutingAssembly()} : args.Select(Assembly.LoadFrom)).ToList(); assembliesToRunOn.AsParallel().ForAll( a => Array.ForEach(a.GetTypes(), t => Array.ForEach(t.GetMethods(BindingFlags.Public | BindingFlags.Instance), mi => { var miParams = mi.GetParameters(); var attribs = mi.GetCustomAttributes(typeof (WebGetAttribute), true); if (attribs.Length <= 0) return; var wga = (WebGetAttribute)attribs[0]; wga.UriTemplate .Split('/') .ToList() .ForEach(tp => { if (tp.StartsWith("{") && tp.EndsWith("}")) { var tpName = tp.Substring(1, tp.Length - 2); if (!miParams.Any(pi => pi.Name == tpName)) { failList.AddOrUpdate(mi, new HashSet<string> {tpName}, (miv, l) => { l.Add(tpName); return l; }); } } }); }))); if (failList.Count == 0) return 0; failList.ToList().ForEach(kvp => Console.Out.WriteLine("Method " + kvp.Key + " in type " + kvp.Key.DeclaringType + " is missing the following expected parameters: " + String.Join(", ", kvp.Value.ToArray()))); return failList.Count; } [WebGet(UriTemplate = "Endpoint/{param1}/{param2}")] public void WillPass(String param1, String param2) { } [WebGet(UriTemplate = "Endpoint/{param1}/{param2}")] public void WillFail() { } [WebGet(UriTemplate = "Endpoint/{param1}/{param2}")] public void WillFail2(String param1) { } } } 
+2
source

Source: https://habr.com/ru/post/1392476/


All Articles