OdeToCode IC Logo

IntelliJ IDEA for Android Development

Monday, January 10, 2011 by K. Scott Allen

imageI really like IntelliJ IDEA - and the free community edition now supports Google Android development.

Part of the reason I like this IDE is because it feels familiar. I've learned the JetBrains sense of style from using ReSharper in Visual Studio, and seeing familiar commands for navigation and refactoring is comforting. It's great to have the muscle memory for Alt+Enter and Alt+Insert, and the auto-completion works well both for Java code and XML resources (which is a tremendous help for someone new to the platform, like myself).

Now I find myself in the wiring up UI events in Java, which feels awkward and verbose coming from C#. I'm also learning the difference between a click and a long click in Android. If you return false from the long click event handler, the event is unhandled and the regular click event handler will also fire. If you return true, the system considers the event handled and the regular click event doesn't fire.

 

public class MainActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)     {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        textView = (TextView)findViewById(R.id.text);
        button =(Button)findViewById(R.id.button);

        button.setOnClickListener(buttonClickListener);
        button.setOnLongClickListener(buttonLongClickListener);
    }

    View.OnClickListener buttonClickListener = new View.OnClickListener(){
        public void onClick(View v) {
            textView.setText("Clicked");
        }
    };

    View.OnLongClickListener buttonLongClickListener = new View.OnLongClickListener() {
        public boolean onLongClick(View v){
            textView.setText("Long click");
            return true;
        }
    };

    private Button button;
    private TextView textView;
}

Razor Tip #1

Thursday, January 6, 2011 by K. Scott Allen

The Razor parser is smart. For example, if you want to display an email address, you can enter the following:

<p>
    Serial@Model.com
</p>

... and Razor will happily output Serial@Model.com into the output - it recognizes the email address.

But what if you want to output a serial number?

<p>
    Serial@Model.SerialNumber
</p>

Unfortunately, Razor still thinks you have an email address and outputs "Serial@Model.SerialNumber". In a few rare cases you have to be more explicit and let the parser know where the C# code begins and ends.

<p>
    <text>Serial</text>@Model.SerialNumber
</p>

But a prettier approach is to use an “explicit code nugget” with parentheses:

<p>
    Serial@(Model.SerialNumber)
</p>

Preprocessed Razor Templates

Wednesday, January 5, 2011 by K. Scott Allen

Preprocessed T4 templates generate all the code you need to execute a template at runtime.

You can do the same "preprocessing" with Razor, but it takes a little more work.

The first step is creating a custom tool for Visual Studio. Visual Studio will feed the template into this tool and expect you to generate the contents of a code file to include in the compilation phase of a project. Visual Studio communicates with the tool using the IVsSingleFileGenerator interface.

[Guid("2678AC94-69B1-4B2B-8939-F15BE231C468")]
public class RazorGenerator : IVsSingleFileGenerator
{
    public int DefaultExtension(out string pbstrDefaultExtension)
    {
        pbstrDefaultExtension = ".cs";
        return pbstrDefaultExtension.Length;
    }

    public int Generate(string wszInputFilePath,
                        string bstrInputFileContents,
                        string wszDefaultNamespace,
                        IntPtr[] rgbOutputFileContents,
                        out uint pcbOutput,
                        IVsGeneratorProgress pGenerateProgress)
    {
        var engine = InitializeEngine(wszDefaultNamespace, 
                                      wszInputFilePath);
        return GenerateCode(wszInputFilePath, engine, 
                            rgbOutputFileContents, out pcbOutput);
    }

    private int GenerateCode(string wszInputFilePath, 
                             RazorTemplateEngine engine, 
                             IntPtr[] rgbOutputFileContents, 
                             out uint pcbOutput)
    {
        using (var file = File.Open(wszInputFilePath, FileMode.Open))
        using (var reader = new StreamReader(file))
        {
            var result = engine.GenerateCode(reader);
            var provider = new CSharpCodeProvider();

            using (var writer = new StringWriter())
            {
                provider.GenerateCodeFromCompileUnit(
                    result.GeneratedCode, writer, 
                    new CodeGeneratorOptions());
                var bytes = Encoding.UTF8.GetBytes(writer.ToString());
                var length = bytes.Length;
                rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length);
                Marshal.Copy(bytes, 0, rgbOutputFileContents[0], length);
                pcbOutput = (uint)length;
                return 0;
            }
        }
    }

    private RazorTemplateEngine InitializeEngine(
                  string wszDefaultNamespace, 
                  string wszInputFilePath)
    {
        var host = new RazorEngineHost(new CSharpRazorCodeLanguage())
        {
          DefaultNamespace = wszDefaultNamespace,
          DefaultClassName = Path.GetFileNameWithoutExtension(
                                             wszInputFilePath)
        };
        return new RazorTemplateEngine(host);
    }
}

Hungarian naming - yuck, but when in COM interop, do as the Hungarians do.

The above class goes into a strong named assembly that you'll GAC and regasm. You also need to make a registry key under HKEY_LOCAL_MACHINE -> SOFTWARE -> Wow6432Node -> Microsoft -> VisualStudio -> 10.0 -> Generators (omit the Wow part on 32 bit systems). Dmitri Nesteruk has a good overview of the process in Custom Tools Explained.

One way to use the template is to provide some base classes:

public class LetterModel
{
    public string FirstName { get; set; }
    public string ShowNumber { get; set; }
}

public abstract class LetterTemplateWriter : RazorWrite
{
    public LetterModel Model { get; set; }        
}

public abstract class RazorWriter
{        
    protected RazorWriter()
    {
        _builder = new StringBuilder();
    }

    public void WriteLiteral(string literal)
    {
        _builder.Append(literal);
    }

    public void Write(object value)
    {
        _builder.Append(value);
    }

    public string GenerateOutput()
    {
        Execute();
        return _builder.ToString();
    }

    public abstract void Execute();
    StringBuilder _builder;
}

And a template:

@inherits LetterTemplateWriter
              

Hi @Model.FirstName,
Thank you for the email. Although our schedules 
are very busy, we decided to take some time and 
write you a personal reply. 

We appreciate the thoughtful feedback on 
show @Model.ShowNumber, and we want to promise 
you, @Model.FirstName, that we will try harder. 

Sincerely, 

Make sure the CustomTool in the file properties window matches your registry key named under Generators:

image

And voila!

var template = new LetterTemplate();
template.Model = new LetterModel() 
{ 
    FirstName = "...", ShowNumber = "..."
};
Console.WriteLine(template.GenerateOutput());

Not as simple as Preprocessed T4 templates, but you can work with the vastly superior Razor syntax. In addition, there is no mucking around with appdomains and runtime compilation. Instead, razor generates the C# code to compile into your project.

Preprocessed T4 Templates

Tuesday, January 4, 2011 by K. Scott Allen

A preprocessed T4 template is an easy, out-of-the-box technology you can use for generating text from a template at runtime. Preprocessed templates are a little different than the T4 templates you might have used in the past. For details, read Oleg Sych's post on the topic

As an example, let's say you add a preprocessed template named "LetterTemplate.tt" to a project, with the following content:

<#@ template language="C#" #>

Hi <#=  Model.FirstName  #>,

Thank you for the email. Although our schedules 
are very busy, we decided to take some time and 
write you a personal reply. 

We appreciate the thoughtful feedback on 
show <#= Model.ShowNumber #>, and we want to promise 
you, <#= Model.FirstName #>, that we will try harder. 

Sincerely, 

For this example, only three pieces of code are required. First there is the partial class to extend the definition of a class generated from the template:

public partial class LetterTemplate
{
    public LetterModel Model { get; set; }
}

Secondly is the definition of LetterModel:

public class LetterModel
{
    public string FirstName { get; set; }
    public string ShowNumber { get; set; }
}

And finally, only a few lines of code are required to execute the template and produce a result.

var template = new LetterTemplate();
template.Model = new LetterModel()
{
    FirstName = "...",
    ShowNumber = "..."
};
var message = template.TransformText();

TranformText is all you need , yet the generation scenarios can be much more complex.

Test First Development Course Online

Monday, January 3, 2011 by K. Scott Allen

David Starr and I recorded a test first development course for Pluralsight's On-Demand! library (subscription required). This is the first course in a series, and we designed the course for someone who is new to the landscape.

I sincerely hope the course helps viewers find a path towards success in software development.

Outline

I. Introduction to Test-First Development

II. Writing Unit Tests (Part I)

III. Writing Unit Tests (Part II)

IV. Introduction to Refactoring

V. Driving Design with Unit Tests

ExpandoObject Explained In Tests (Except For One Mystery)

Monday, November 8, 2010 by K. Scott Allen

Update: Thanks to James and Samuel.  I’ve wrongly assumed that every test runner in the world re-instantiates the test fixture before executing each test method – but some do and some don’t. In this case I was using NUnit and the “mystery” is solved by adding an NUnit [Setup] method to create a fresh, new expando for each test run. Seems obvious, but only after ejecting all assumptions.

xUnit.net and the Visual Studio mstest tools DO create a fresh instance of the test fixture for each test method they execute inside the fixture. NUnit and MBUnit only create the fixture once, and as Jim Newkirk says:

I think one of the biggest screw-ups that was made when we wrote NUnit V2.0 was to not create a new instance of the test fixture class for each contained test method. I say "we" but I think this one was my fault. I did not quite understand the reasoning in JUnit for creating a new instance of the test fixture for each test method. I look back now and see that reusing the instance for each test method allows someone to store a member variable from one test and use it another. This can introduce execution order dependencies which for this type of testing is an anti-pattern.

The anti-pattern is demonstrated below. Smile

 

The following tests all pass for .NET 4.0’s ExpandoObject.

private dynamic expando = new ExpandoObject();

[Test]
public void Can_Add_A_Member()
{
    var expected = "Scott";            
    expando.Name = expected;
    
    Assert.AreEqual(expected, expando.Name);
}

[Test]
public void But_Cannot_Reflect_It()
{
    expando.Name = "Scott";

    Assert.IsNull(expando.GetType().GetProperty("Name"));           
}

[Test]
public void Is_A_Dictionary()
{
    var expected = "Scott";
    var dictionary = expando as IDictionary<string, object>;
    expando.Name = expected;

    Assert.AreEqual(expected, dictionary["Name"]);
}

[Test]
public void And_Also_Enumerable()
{
    var enumerable = expando 
             as IEnumerable<KeyValuePair<string, object>>;
    expando.Name = "Scott";

    Assert.IsTrue(enumerable.Any(kv => kv.Key == "Name"));
}

What’s The Mystery?

ExpandoObject implements INotifyPropertyChanged and the following test will pass.

[Test]
public void Will_Raise_PropertyChangedEvent()
{            
    dynamic expando = new ExpandoObject();
    var propertyName = "";
    ((INotifyPropertyChanged)expando).PropertyChanged +=
        (sender, args) => 
        {               
            propertyName = args.PropertyName;
        };
    expando.Name = "Scott";
    
    Assert.AreEqual("Name", propertyName);
}   

But, this version of the test fails unless you run under the debugger.

private dynamic expando = new ExpandoObject();        

[Test]
public void Will_Raise_PropertyChangedEvent()
{                        
    var propertyName = "";
    ((INotifyPropertyChanged)expando).PropertyChanged +=
        (sender, args) => 
        {               
            propertyName = args.PropertyName;
        };
    expando.Name = "Scott";
    
    Assert.AreEqual("Name", propertyName);
}   

In the passing test expando is local variable. In the failing test expando is a field. Scary.

Notes on Templates and Data Annotations in MVC 2

Sunday, July 25, 2010 by K. Scott Allen

Brad Wilson has an excellent series of 5 blog posts on model metadata and templates you can use to get started with templates and metadata in ASP.NET MVC 2. Here are a couple notes I've made around some of aspects that commonly confuse developers (including me, it seems).

1. Although most of the metadata attributes live in the System.ComponentModel.DataAnnotations namespace, there are a few exceptions. If you aren't seeing something you need in Intellisense, then try adding System.ComponentModel (for the popular DisplayName attribute) and System.Web.Mvc (for the popular HiddenInput attribute).

2. Some of the confusion around data annotations exists because the MVC runtime doesn't recognize every data annotation attribute built into .NET. For example, using [Editable(false)] is tempting, but you'll find it doesn't have any impact in model binding, validation, or templating. The built-in templates respect 7 data annotation attributes:

  • DisplayColumn
  • HiddenInput
  • UIHint
  • DataType
  • DisplayFormat
  • ScaffoldColumn
  • DisplayName

3. There are two additional attributes the default model metadata provider will consume:

  • ReadOnly
  • Required

However, the built-in templates do not make use of the information from these attributes. For example, you can apply [ReadOnly(true)] to a property, but you'll find the default templates in use by helpers like Html.EditorForModel will still show a textbox input for the user to enter a value. If you want to get rid of the input with EditorForModel you'll need a custom template, or you'll need to use [ScaffoldColumn(false)].

Note the default model binder does respect the ReadOnly attribute, so it won't move a value into a property with [ReadOnly[false)]. Also, the built-in validation logic respects the Required attribute. These attributes definitely have value in an MVC app, but they won't influence the UI rendered by the default templates.