Simple Adaptive Access Layer HelloWorld Sample

After having read the MSDN article Adaptive Access Layers + Dependency Injection = Productivity and having Ulrik come tell us about AAL, I felt it could be a good exercise to create the smallest possible AAL sample. This is what I could come up with, using Roslyn as code-generator, and the LogAccessLayerAttribute class as the source code generator.

Adding a new method to the ISampleLog interface will automatically create a new concrete method in the generated SampleLog.cs class.

Program.cs
  1. namespace HelloWorldAdaptiveAccessLayerSample
  2. {
  3.     class Program
  4.     {
  5.         static void Main(string[] args)
  6.         {
  7.             var logger = MyContainer.GetService<ISampleLog>();
  8.             logger.ThisIsAWarning(100);
  9.             logger.ThisIsAnError(99);
  10.             logger.ThisIsAWarning(101);
  11.         }
  12.     }
  13. }
ISampleLog
  1. namespace HelloWorldAdaptiveAccessLayerSample
  2. {
  3.     using System.Diagnostics;
  4.     [LogAccessLayer]
  5.     public interface ISampleLog
  6.     {
  7.         [LogEntry(1, TraceEventType.Warning, “HelloWorld warning {0}”)]
  8.         void ThisIsAWarning(int warningNumber);
  9.         [LogEntry(2, TraceEventType.Error, “HelloWorld error {0}”)]
  10.         void ThisIsAnError(int errorNumber);
  11.     }
  12. }
MyContainer.cs
  1. namespace HelloWorldAdaptiveAccessLayerSample
  2. {
  3.     using System;
  4.     using System.IO;
  5.     using System.Linq;
  6.     using System.Reflection;
  7.     using Roslyn.Compilers;
  8.     using Roslyn.Compilers.CSharp;
  9.     public static class MyContainer
  10.     {
  11.         public static T GetService<T>()
  12.         {
  13.             var factory = GetServiceFactory<T>();
  14.             var sourceText = factory.GetSourceText(typeof(T).GetMethods());
  15.             var co = new CompilationOptions(OutputKind.DynamicallyLinkedLibrary);
  16.             SyntaxTree tree = SyntaxTree.ParseText(sourceText);
  17.             MetadataReference mscorlib = MetadataReference.CreateAssemblyReference(“mscorlib”);
  18.             var helloWorld = new MetadataFileReference(typeof(MyContainer).Assembly.Location);
  19.             Compilation compilation = Compilation.Create(factory.GetTypeName(), co)
  20.                             .AddReferences(mscorlib)
  21.                             .AddReferences(helloWorld)
  22.                             .AddSyntaxTrees(tree);
  23.             var sampleAssemblyName = Path.Combine(Path.GetDirectoryName(typeof(MyContainer).Assembly.Location), “SampleLog.dll”);
  24.             using (var stream = new FileStream(sampleAssemblyName, FileMode.Create))
  25.             {
  26.                 var result = compilation.Emit(stream);
  27.             }
  28.             var asm = Assembly.LoadFile(sampleAssemblyName);
  29.             var type = asm.GetTypes().Where(p => p.Name.Equals(factory.GetTypeName())).SingleOrDefault();
  30.             return (T)(object)Activator.CreateInstance(type, false);
  31.         }
  32.         privatestaticIServiceFactory GetServiceFactory<T>()
  33.         {
  34.             var t = typeof(T);
  35.             var logAccessLayer = t.GetCustomAttribute<LogAccessLayerAttribute>();
  36.             if (logAccessLayer != null)
  37.             {
  38.                 var instance = Activator.CreateInstance<LogAccessLayerAttribute>() asIServiceFactory;
  39.                 return instance;
  40.             }
  41.             return null;
  42.         }
  43.     }
  44. }
IServiceFactory.cs
  1. namespace HelloWorldAdaptiveAccessLayerSample
  2. {
  3.     using System.Reflection;
  4.     public interface IServiceFactory
  5.     {
  6.         string GetSourceText(MethodInfo[] methods);
  7.         string GetTypeName();
  8.     }
  9. }
LogAccessLayerAttribute.cs
  1. namespace HelloWorldAdaptiveAccessLayerSample
  2. {
  3.     using System;
  4.     using System.Reflection;
  5.     using System.Text;
  6.     class LogAccessLayerAttribute : Attribute, IServiceFactory
  7.     {
  8.         public static LogAccessLayerAttribute GetFactory()
  9.         {
  10.             return new LogAccessLayerAttribute();
  11.         }
  12.         publicstring GetSourceText(MethodInfo[] methods)
  13.         {
  14.             var sourceText =
  15.                 @”namespace HelloWorldAdaptiveAccessLayerSample
  16.                 {
  17.                     using System;
  18.                     public class SampleLog : ISampleLog
  19.                     {
  20.                         public SampleLog() { }
  21.                         // ##Methods
  22.                     }
  23.                 }”;
  24.             var sb = newStringBuilder();
  25.             foreach(var method in methods)
  26.             {
  27.                 var arguments = GetArguments(method);
  28.                 var signature = string.Format(“{0} {1} {2}({3})”,
  29.                     method.IsPublic ? “public” : “private”,
  30.                     GetReturnType(method.ReturnType),
  31.                     method.Name,
  32.                     arguments);
  33.                 sb.Append(signature);
  34.                 var logEntry = method.GetCustomAttribute<LogEntryAttribute>();
  35.                 if (logEntry != null)
  36.                 {
  37.                     sb.AppendLine(“{“);
  38.                     if (logEntry.TraceEventType == System.Diagnostics.TraceEventType.Error)
  39.                     {
  40.                         sb.AppendLine(“Console.ForegroundColor = ConsoleColor.DarkRed;”);
  41.                     }
  42.                     sb.AppendLine(string.Format(”    Console.WriteLine(\”{0} {1}\”, {2});”, logEntry.FormatString, logEntry.EventId, method.GetParameters()[0].Name));
  43.                     if (logEntry.TraceEventType == System.Diagnostics.TraceEventType.Error)
  44.                     {
  45.                         sb.AppendLine(“Console.ForegroundColor = ConsoleColor.White;”);
  46.                     }
  47.                     sb.AppendLine(“}”);
  48.                 }
  49.             }
  50.             return sourceText.Replace(“// ##Methods”, sb.ToString());
  51.         }
  52.         privatestring GetReturnType(Type type)
  53.         {
  54.             switch(type.ToString())
  55.             {
  56.                 case“System.Void”:
  57.                     return“void”;
  58.                 default:
  59.                     return type.ToString();
  60.             }
  61.         }
  62.         publicstring GetTypeName()
  63.         {
  64.             return“SampleLog”;
  65.         }
  66.         privatestring GetArguments(MethodInfo method)
  67.         {
  68.             var sb = newStringBuilder();
  69.             foreach (var parameter in method.GetParameters())
  70.             {
  71.                 sb.Append(string.Format(“{0} {1},”, parameter.ParameterType.ToString(), parameter.Name));
  72.             }
  73.             return sb.ToString().Substring(0, sb.Length – 1);
  74.         }
  75.     }
  76. }
LogEntryAttribute.cs
  1. namespace HelloWorldAdaptiveAccessLayerSample
  2. {
  3.     using System;
  4.     using System.Diagnostics;
  5.     public class LogEntryAttribute : Attribute
  6.     {
  7.         public int EventId { get; privateset; }
  8.         public TraceEventType TraceEventType { get; privateset; }
  9.         public string FormatString { get; privateset; }
  10.         public LogEntryAttribute(int eventId, TraceEventType traceType, string formatString)
  11.         {
  12.             this.EventId = eventId;
  13.             this.TraceEventType = traceType;
  14.             this.FormatString = formatString;
  15.         }
  16.     }
  17. }
Posted in Uncategorized | Leave a comment

Tfs Release Notes published on CodePlex

Thanks to popular demand (thank you Rob), I’ve published the source code on https://tfsreleasenotes.codeplex.com/.

Please expect to do some work before you get it up and running, there’s no documentation yet.

To get you started, look at the  build template https://tfsreleasenotes.codeplex.com/SourceControl/changeset/view/98304#2384786 which contains the BRN activity.

Cheers,

/Gert

Posted in Uncategorized | Leave a comment

Dude, where’s my Visual Studio 2012 Test Explorer window?

I’ve been using VSTS 2012 for a while, and after uninstalling the Test Agent from my dev box, I suddenly experienced an error when trying to open the Test Explorer window.

The composition produced a single composition error. The root cause is provided below.  Review the CompositionException.Errors property for more detailed information.
1) Value cannot be null. Parameter name: testPlatform
Resulting in: An exception occurred while trying to create an instance of type ‘Microsoft.VisualStudio.TestWindow.Model.ReqeustConfigurationFactory’.
Resulting in: Cannot activate part ‘Microsoft.VisualStudio.TestWindow.Model.ReqeustConfigurationFactory’. Element: Microsoft.VisualStudio.TestWindow.Model.ReqeustConfigurationFactory –> Microsoft.VisualStudio.TestWindow.Model.ReqeustConfigurationFactory –> CachedAssemblyCatalog
Resulting in: Cannot get export Microsoft.VisualStudio.TestWindow.Model.ReqeustConfigurationFactory (ContractName=”Microsoft.VisualStudio.TestWindow.Model.RequestConfigurationFactory”)’ from part ‘Microsoft.VisualStudio.TestWindow.Model.ReqeustConfigurationFactory’. Element: Microsoft.VisualStudio.TestWindow.Model.ReqeustConfigurationFactory (ContractName=”Microsoft.VisualStudio.TestWindow.Model.RequestConfigurationFactory”)

After posting a Connect error, and no luck running devenv.exe /setup, I decided to see what Procmon had to say about this. Procmon showed that the file USERDIR\AppData\Local\Microsoft\VisualStudio\11.0\ComponentModelCache\Microsoft.VisualStudio.Default.cache was being used.

After deleting the file and restarting VS, I could now see the Test Explorer window again. Oh joy.

/Gert

Posted in VSTS 2012 RC | 2 Comments

TFS and a SSAS named instance

A client saw this error when trying to execute the reports:

An error has occurred during report processing. (rsProcessingAborted)
Cannot create a connection to data source ‘TfsOlapReportDS’. (rsErrorOpeningConnection)
For more information about this error navigate to the report server on the local server machine, or enable remote errors

They were puzzled because the reports had worked before, so the investigation started. Naturally I asked for a BPA report, but it only showed SOAP errors, and they were not related to the reporting error.

We could connect to the datawarehouse and the cube (after using the correct credentials) from another box other than the TFS AT, so the problem must be between the AT and the DT.

After some googling, the problem was found; it turns out that if you use a named instance for the cube, SSAS uses dynamic ports. The reason why it had worked before was that the SSAS service started, got assigned a port, the installer person/tfs administrator noticed the assigned port and opened for the dynamically assigned port in the firewall. Next time SSAS started, a new port was assigned and the connection failed causing the error.

After configuring a fixed port in the SSAS config file for the new port the connection worked just fine. Just to be sure that we did it correctly, we restarted the instance and the report failed again.

Turned out we edited the wrong SSAS config file, after finding the right one for the instance being used, making the correction and restarting the instance, it now worked.

Lessons learned:

  • Reboot all TFS tiers after an installation and then do the test to make sure that transient changes are out of the picture.
  • It would be great if BPA could find this particular problem 🙂

/Gert

Posted in TFS Administration | Tagged , , | Leave a comment

Dev343 – Implementing Team Foundation Server in the Enterprise: Guide to a Successful Implementation

Takeaways from the talk:

  • “Culture eats strategy for lunch”
  • Tool training -> train the process for achieving the goal
  • Max number of team projects in a collection: ~2000 (depends on a number of aspects, including number of process templates, number of fields…)
  • Tfs: Mission Critical -> Tfs 2012 -> SQL Server 2012 Always On, Geo-location independent
  • Project meta-data (WI): Owner, Process model, architecture info for potential reuse
Posted in ALM | Leave a comment

Generate Build Release Notes in MS Word using Tfs Team Build and the OpenXML 2.0 SDK

Build Release notes in MS Word can be generated automatically using Tfs TeamBuild and the OpenXML 2.0 SDK. The OpenXML 2.0 SDK has a steep learning curve, but luckily Atul created this http://worddocgenerator.codeplex.com/ project to smooth the curve out.

The pictures below are from a sample build release note created by a custom build activity that extracts changesets associated to the build, the merges and all changesets between this build and the previous build.

So how is the previous build found?

You specify the build quality; e.g. “Released” in the build release notes build and it will find the latest successfull build with set build quality.

The actual generation is performed by a build release notes build kicked off by the primary build; the build you want the release notes created for. This was done in order for the build detail to contain the configurations compiled during the build process; the configuration summaries information is not available during the build, only after the build has finished. The primary build queues a build release notes build with the current BuildUri so that the build release notes build can read the finished build information for the primary build.

Frontpage - Build Release Notes

Frontpage – Build Release Notes

Abstract and build summary - Build Release Notes

Abstract and build summary – Build Release Notes

Configurations and projects - Build Release Notes

Configurations and projects – Build Release Notes

Changesets - Build Release Notes

Changesets – Build Release Notes

WorkItems - Build Release Notes

WorkItems – Build Release Notes

Test case results - Build Release Notes

Test case results – Build Release Notes

Posted in TeamBuild, TFS 11, tfspreview.com, VSTS 11 Beta | Tagged , , | 2 Comments

Hello world!

Welcome to WordPress.com. This is your first post. Edit or delete it and start blogging!

Posted in Uncategorized | 1 Comment

Taler om Solution : Core SSD’s freezing and stuttering(WinXP)

 
Disable short file names to speed up Windows
fsutil behavior set disable8dot3 1
 
Disable timestamp for last access to a file to speed up Windows
fsutil behavior set disablelastaccess 1
Disable the NTFS Change Journal
fsutil usn deletejournal /d c:
Turn off Windows Prefetch following these instructions
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Contro l\Session Manager\Memory Management\PrefetchParameters]
"EnablePrefetcher"=dword:00000000
Intel Driver Update Utility
 
 
 
 
Posted in SSD | Leave a comment

Linq Over Tfs

I wish that I could do this:
 
var tfs = new TfsLinqProvider("http://tfs1:8080")
var 2008Solutions = from p in tfs.Solutions
                              where p.SolutionVersion.Equals(SolutionVersion.VS2008)
                              select p;
 
var solutionsWithWixProjects = from p in tfs.Solutions
                               from o in p.Projects
                               where o.ProjectType.Equals(ProjectType.WixProject)
                               select p;
 
var whenWasDebugAssertAdded = from p in tfs.SourceFiles
                              where p.FileType.Equals(FileType.CSharpFile) && p.Contains("Debug.Assert")
                              select new { p.SourceFile, p.ProjectFile, p.SolutionFile, p.IntroducedInChangeSet };
 
var top10MostEditedFiles = ((from p in tfs.SourceFiles
                                         select p).OrderBy( p => p.ChangeSets.Count()) desc).Take(10);
 
That would be sweet…
 
 
 
 
Posted in VSTS | Leave a comment

Show Hintpath references for all Visual Studio .csproj projects

It could be challenge to get an overview of all Hintpath references for a large number of Visual Studio projects if it were not for PowerShell v2:

gci . -Filter *.csproj -Recurse|gc|?{$_ -match "<Hintpath Include="}|sort|group|select Name|out-gridview

Posted in VS2010 | Leave a comment