Showing posts with label code. Show all posts
Showing posts with label code. Show all posts

2010-02-04

DesignMode in Visual Studio, inheritance, process name and a work around

The text and code below is only tested for Winform. WPF might behave differently; hopefully behaves differently.

I won't go into any details on why the ISite.DesignMode is good and sometimes even crucial to have. It is much better done in the link at the bottom.

First out there is unfortunately a caveat with DesignMode, it doesn't work with inherited forms and user controls. This is a problem since I always inherit from the base form in my projects and tell others to do the same. It also doesn't work inside the form's or the user control's constructor and then by any method that is called by the constructor. Long call chains to might make this hard to track down.
Secondly there is another way to check for design mode and that is to check for the LicenseManager.UsageMode but this in turn doesn't work in event handlers.
Thirdly one can set a flag in the base Form and base UserControl. But this doesn't solve the problem since we cannot be sure with what to set this value.
Fourthly is a workaround where one can check for the name of the process itself which is Visual Studio's process name (devenv) in case of design mode. This process name might change in future releases of Visual Studio and is also different for other IDEs.
Fifthly is other process information like the name of the module and stuff. Check into the Process and you'll see that the app is called MyApp.vshost.exe while being debugged.

The fourth solution (processname=devenv) seems to be the most viable but I believe there is something useful in the fifth (other process information). There must be a way to notice that the name of all your code doesn't match the name of the running environment; namespace, assembly name, whatever. I still haven't figured out how though.

Below is some code to copy-paste.
It is not 100% correct though since the DesignMode property isn't virtual. This might end with some really tough-to-track-down bugs where one iterates the forms but don't get the overloaded DesignMode flag. The code also doesn't promise to work forever since there is a magic string naming the name of the Visual Studio process.


public partial class MyAppForm : System.Windows.Forms.Form
{
protected new bool DesignMode
{
get
{
return HelperMethods.IsDesignMode(this);
}
}
}

public partial class MyAppUserControl : UserControl
{
protected new bool DesignMode
{
get
{
return HelperMethods.IsDesignMode(this);
}
}
}

class HelperMethods
{
public static bool IsDesignMode(System.ComponentModel.Component x)
{
var site = x as System.ComponentModel.ISite;
return
( null == site ? false : site.DesignMode ) ||
System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime ||
System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv";
}
}
The code above is also in pastebin for easier copy-paste.
A good article is here: http://dotnetfacts.blogspot.com/2009/01/identifying-run-time-and-design-mode.html
There is a description of how to debug this here: http://brennan.offwhite.net/blog/2006/08/30/design-time-debugging-aspnet-20-in-visual-studio-2005/

2010-01-16

Get calling method's name automatically in dotnet

Way too many times have I written

void MyFunction( int aNumber)
{
MyHomemadeLogClass.Logg( "MyFunction", "aNumber=" + aNumber.ToString());
...
}
to get logging functionality.

It would be so nice to just write

void MyFunction( int aNumber)
{
MyHomemadeLogClass.Logg();
...
}
It is no hard to do. Use reflection to get the call stack to get to the method and the parameters. Convert all this to a readable string.
Unfortunately it is not that easy to log the contents of the parameters, one has to get into some sort of debugger area to do that.

class ReflectionUtility
{
private static System.Reflection.MethodBase GetCallingMethod()
{
return new System.Diagnostics.StackTrace().GetFrame(2).GetMethod();
}
public static string GetCallingMethodFullNameReturnParametertypes()
{
return MethodFullNameReturnParametertypes(GetCallingMethod());
}
private static string MethodFullNameReturnParametertypes(System.Reflection.MethodBase method)
{
return string.Format("{0} {1}.{2} ({3})",
((System.Reflection.MethodInfo)method).ReturnType, // System.Void, System.Int32 etc.
method.DeclaringType.FullName, // MyNamespace.MyClass.
method.Name, // MyMethod.
string.Join(",", method.GetParameters().Select(p => p.ParameterType.ToString() + " " + p.Name).ToArray()) // () or (int) or (int,string) etc.
);
}
}
To use this in a Logging class one must implement a GetCallingCallingMethod or even worse, but it would make this example hard to read.

One can use the Conditional attribute to avoid the call when not debugging.

I also put the code on pastebin to make the copy-paste easier. (I have yet to find a good way to present code.)

2010-01-06

Catch property, field and method name changes compile time in dotnet

When you want to populate a dropdown listbox with customers

class Customer
{
int Id;
string Name;
...
}
and have to write

myDropdownListbox.DisplayMember = "Name";
myDropdownListbox.DataMember = "Id";
or

myGridColumnCustomerName.DatatMeber = "Name";
you really get a sour taste in your mouth.

Having magic strings like above spread in your code is really bad since it always compiles but might fail runtime. This means more manual tests. Which in turns means a certain friction against renaming properties while refactoring.
I have been in way too many projects where one table has a field ItemNumber when it should have been ItemCount and where some fields are called Nr while another Number and these names are spread up in the layers to reach the presentation layer where they surface as magic strings like the examples above.

Luckily there is a solution in Dotnet 3 with LINQ. It isn't the prettiest but it fails compile time when it should and that is considered a good thing.

( I won't bother with explanation - just read the code. )

// The Code.
class ReflectionUtility
{

public static string GetPropertyName<T,TReturn>(Expression<Func<T,TReturn>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}

public static string GetMethodName<T,TReturn>(Expression<Func<T,TReturn>> expression)
{
var body = expression.Body as UnaryExpression;
var operand = body.Operand as MethodCallExpression;
var argument = operand.Arguments[2] as ConstantExpression;
var methodInfo = argument.Value as System.Reflection.MethodInfo;

return methodInfo.Name;
}

}

// The test code.
class MyClass
{
public int MyField;
public int MyPublicProperty { get; set; }
public string MyReadonlyProperty { get { return string.Empty; } }
public int MyMethod() { return 0; }

private MyClass() { } // To make sure the class doesn't need a default constructor.
}

class Program
{
static void Main(string[] args)
{
string fieldName = ReflectionUtility.GetPropertyName((MyClass x) => x.MyField);
Console.WriteLine(string.Format("MyClass.MyField:{0}", fieldName));
Debug.Assert("MyField" == fieldName);

string propertyName = ReflectionUtility.GetPropertyName((MyClass x) => x.MyPublicProperty);
Console.WriteLine(string.Format("MyClass.MyPublicProperty:{0}", propertyName));
Debug.Assert("MyPublicProperty" == propertyName);

propertyName = ReflectionUtility.GetPropertyName((MyClass x) => x.MyReadonlyProperty);
Console.WriteLine(string.Format("MyClass.MyReadonlyProperty :{0}", propertyName));
Debug.Assert("MyReadonlyProperty" == propertyName);

string methodName = ReflectionUtility.GetMethodName<MyClass, Func<int>>((MyClass x) => x.MyMethod);
Console.Write(string.Format("MyClass.MyMethod:{0}", methodName));
Debug.Assert( "MyMethod" == methodName);

Console.Write(Environment.NewLine + "Press any key.");
Console.ReadKey();
}

}
Honor those who should.

Update: When copy-pasting through manoli.net some angle brackets got dropped. This is, hopefully, fixed now.  Otherwise - get the source here: http://selfelected.pastebin.com/f77563a02

2009-07-22

NUnitEx

NUnitEx is an extension to NUnit.  It makes the assertions more of a flow to write.

Instead of writing

string myString = MyMethod();
Assert.AreEqual( "selfelected", myString );
one writes
string myString = MyMethod();
myString.Should().Be.EqualTo( "selfelected" );
A good thing with the former approach is that the coloured syntax makes it easier to distinquish method calls from assertions.

But when one tests exception throwing nunitex is the way to go.

Originally one had to write one method per call that threw an exception.  Even as a happy typist I think it was too much.  Nunitex easily handles exception throwing calls almost as ordinary calls.

See the example code at http://code.google.com/p/nunitex/ for yourself.

2009-04-17

Timer and GUI

One cannot use the System.Timers.Timer to update the GUI, instead one gets a cross-thread exception. The GUI can't be updated from another thread.

A nice trick to solve this is to use a method that is sensitive for if the call comes from another thread than the GUI is running on.



private delegate void SetTextDelegate(Label label, string text);

private void SetText(Label label, string text)
{
if (this.InvokeRequired)
{
IAsyncResult res = BeginInvoke(new SetTextDelegate(SetText), label, text);
EndInvoke(res);
}
label.Text = text;
}


Honor those who should.

2009-04-11

Attach to a process even faster

In an earlier article I mentioned a time saver for web projects where I recommended attaching to the process instead of restarting every time.

Today I invested time in creating a macro for attaching to the Nunit process.  It was easy.

- Instead of learning all commands just record a new macro (menu->tools->macro->record temporarymacro) and connect to the process of choice.

- Then open the macro explorer (menu->tools->menu->macro explorer) which opens a toolbox.  There is a (new) module called RecordingModule.  Open this.

A new IDE opens with something like:




Sub AttachToNUnitProcess()
' MsgBox("AttachToNUnitProcess.Start")
Try
Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
Dim dbgeng(1) As EnvDTE80.Engine
dbgeng(0) = trans.Engines.Item("Managed") ' Can be "Native".
Dim proc2 As EnvDTE80.Process2 = dbg2.GetProcesses(trans, "MDG-VILTERSTEN").Item("nunit.exe")
proc2.Attach2(dbgeng)
Catch ex As System.Exception
MsgBox(ex.Message)
End Try
' MsgBox("AttachToNUnitProcess.Slut")
End Sub

- Testrun your macro in Visualstudio just to make sure it runs properly.

- In the macro editor, create a new Module and copy the code you just created.  Rename module and method.  Save.

- Back in Visualstudio, Macro explorer, your new module should be visible.  "Should" - one might have to restart Visualstudio or the toolbox or something.  It should be runnable directly from the Macro explorer toolbox.

- Create a new menu (menu->tools->customize ...) and attach your macro.  You find it under "Categories/Macros", just drag it to your new menu or the menu bar.

Now attaching to a process is just a click or keystroke away.

Some more info is found here: http://msdn.microsoft.com/en-us/library/hdf2d1z8(VS.80).aspx.

Update: I debugged a web app for a while yesterday and Wow! - what a difference between 3 clicks and 1 click, or 3 keystrokes and 1 keystroke.  Besides being simpler it also connected faster when the GUI didn't have to render and didn't have to wait for me.  Why haven't I done this years ago?  What else is there I should have done years ago?

Update: I created a new menu and items for every macro I use.  So Fast to use!
There is something that bothers me though.  Some menues dissappear after I restart VSNet, I don't know why.

The macros are easy to start also without having created a menu for them.  Just alt-F8 and then arrow keys to find the right macro and start it with return.

2009-03-20

A tip for writing Xml comments in Csharp

There is something called xml comments in the dotnet world.

It looks something like

/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public User FindUser( string name )
{...


The trick here is to write the comments on the very first line. Like:

/// <summary>This method finds and returns a User by its name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public User FindUser( string name )
{...


When the code is folded it then looks like

/// <summary>This method finds and returns a User by its name. ...
public User FindUser( string name )...


Visual Studio "suggests" writing the comments on line two, like

/// <summary>
/// This method finds and returns a User by its name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public User FindUser( string name )
{...


but then after folding it looks like

/// <summary> ...
public User FindUser( string name )...


(this is not a problem in vbnet)