Latest Entries »

So a teammate of mine changed jobs recently, and left a little bit of mess behind on TFS (our team uses TFS Preview). Pending changes including adding package items with exclusive lock. As I’ve been looking for an information on how to drop his pending changes, it turned out quite easy to perform for existing files (change type: edit, lock), yet not for all new files (change type: add, lock).

Here’s a bunch of commands you can run on your local dev machine from the Visual Studio Command Prompt. You need to have admin rights on TFS for the project in order to do something more than listing.

LIST WORKSPACES OWNED BY user@domain.com

tf workspaces /owner:user@domain.com
              /collection:https://yourproject.tfspreview.com/defaultcollection

LIST ALL PENDING CHANGES IN WORKSPACENAME;user@domain.com

tf status $/PROJECTNAME/* /workspace:WORKSPACENAME;user@domain.com
          /collection:https://yourproject.tfspreview.com/defaultcollection
          /recursive

UNDO ALL PEDING CHANGES IN WORKSPACENAME;user@domain.com

tf undo $/PROJECTNAME/* /workspace:WORKSPACENAME;user@domain.com
        /collection:https://yourproject.tfspreview.com/defaultcollection
        /recursive

References

In various scenarios, there is a need for referring to a property via a string containing its name. Probably the most common case is when invoking the PropertyChanged event handler:

// Notify that property value has changed.
PropertyChanged(this, new PropertyChangedEventArgs("SomePropertyName"));

Obviously this is error prone. When it comes to string values, a typo can easily be done. The solution to this problem is to get the property name automatically from the property reference. This is where lambda expressions become handy. () => Property or x => x.Property lets you perceive any faults during compile time or even earlier during design time.

To clarify, I’m not discovering anything new here, nor reinventing the wheel. For several years, the subject has been known, discussed, and implemented. While reviewing a few implementations I stumbled across, I decided to create my own variation, anyway to put together some features scattered around.

Usage

The PropertyName helper class can be used to retrieve the property name of static and non-static properties from object instances and types directly. It is also possible to get property names from nested properties. Some examples:

// Get the property name form object instance
var obj = new SampleObject();
var name1 = PropertyName.For(() => obj.SampleProperty);
Assert.AreEqual("SampleProperty", name1);

// Get the property name form within object instance
var name2 = PropertyName.For(() => this.SampleProperty);
Assert.AreEqual("SampleProperty", name2);

// Get the name of a static property
var name3 = PropertyName.For(() => SampleType.StaticProperty);
Assert.AreEqual("StaticProperty", name3);

// Get the property name from a type
var name4 = PropertyName.For<SampleType>(x => x.SampleProperty);
Assert.AreEqual("SampleProperty", name4);

// Get the name of a nested property from object instance and type
var name5 = PropertyName.For(() => this.SampleProperty.NestedProperty);
var name6 = PropertyName.For<SampleType>(x => x.SampleProperty.NestedProperty);
Assert.AreEqual("SampleProperty.NestedProperty", name5);
Assert.AreEqual("SampleProperty.NestedProperty", name6);

Source code

Below is the full code of the PropertyName helper class:

/// <summary>
/// Returns the name of the property using lambda expression.
/// </summary>
public sealed class PropertyName
{
	/// <summary>
	/// Error message in case lambda expression does not contain a property.
	/// </summary>
	private const string _ErrorMessage = "Expression '{0}' does not contain a property.";

	/// <summary>
	/// Returns the name of the property using lambda expression.
	/// </summary>
	/// <typeparam name="T">Type containing the property.</typeparam>
	/// <param name="propertyExpression">Expression containing the property.</param>
	/// <returns>The name of the property.</returns>
	public static string For<T>(Expression<Func<T, object>> propertyExpression)
	{
		if (propertyExpression == null)
		{
			throw new ArgumentNullException("propertyExpression");
		}
		var body = propertyExpression.Body;
		return GetPropertyName(body);
	}

	/// <summary>
	/// Returns the name of the property using lambda expression.
	/// </summary>
	/// <param name="propertyExpression">Expression containing the property.</param>
	/// <returns>The name of the property.</returns>
	public static string For(Expression<Func<object>> propertyExpression)
	{
		if (propertyExpression == null)
		{
			throw new ArgumentNullException("propertyExpression");
		}
		var body = propertyExpression.Body;
		return GetPropertyName(body);
	}

	/// <summary>
	/// Returns the name of the property using lambda expression.
	/// </summary>
	/// <param name="propertyExpression">Expression containing the property.</param>
	/// <param name="nested">Is it a recurrent invocation?</param>
	/// <returns>The name of the property.</returns>
	private static string GetPropertyName(Expression propertyExpression, bool nested = false)
	{
		MemberExpression memberExpression;

		if (propertyExpression is UnaryExpression)
		{
			var unaryExpression = (UnaryExpression)propertyExpression;
			memberExpression = unaryExpression.Operand as MemberExpression;
		}
		else
		{
			memberExpression = propertyExpression as MemberExpression;
		}

		if (memberExpression == null)
		{
			if (nested) return string.Empty;
			throw new ArgumentException(string.Format(_ErrorMessage, propertyExpression),
										"propertyExpression");
		}

		var propertyInfo = memberExpression.Member as PropertyInfo;
		if (propertyInfo == null)
		{
			if (nested) return string.Empty;
			throw new ArgumentException(string.Format(_ErrorMessage, propertyExpression),
										"propertyExpression");
		}

		return (memberExpression.Expression != null &&
				memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
					? GetPropertyName(memberExpression.Expression, true) + propertyInfo.Name
					: propertyInfo.Name + (nested ? "." : string.Empty);
	}
}

Some light on the main code

Now, let us discuss the body of the GetPropertyName method. The expression containing a property of the reference type is of the MemberExpression type. Nothing unusual here. For a property of value type it is of UnaryExpression type, however. Its Operand member contains the value of MemberExpression that we are interested in. In other words, an expression containing a value type property is boxed and we need to unbox it.

Since there are other expression types that might accidentally sail in, we cannot explicitly cast an expression to MemberExpression but use as operator and check for nullity.

The propertyInfo block is just for ensuring that we are getting the name of a property. Generally, this part could be dropped and the class called MemberName.

Let’s move on to the return statement and recurrence that occurs here. It is designed to get the nested properties, e.g., x => x.SomeProperty.SomeSubProperty.OrEvenMore. The order of property names retrieval is bottom-up. The first chunk returned for the example above is OrEvenMore, then SomeSubProperty and SomeProperty, respectively.

The if (nested) return string.Empty; conditional statement is used to enable
() => obj.SomeProperty
The obj chunk fits the return statements conditions and GetPropertyName method is invoked recurrently. It may seem not to be the neatest solution, but it’s the best I came up with for the moment. Got any hints regarding this issue, please let me know.

References

Having guidelines in your code editor makes it a bit easier to maintain your code in a tidy manner. For Visual Studio 2010, I use these free extensions:

  • Indent Guides by Steve Dower – displays indent guides in Visual Studio text editor windows.
  • Editor Guidelines by Paul Harrington – adds vertical guidelines behind the text at user-specified column positions.
  • Editor Guidelines UI by Paul Harrington – adds submenu with three commands to the code editor’s context menu (right click) for managing editor guidelines – no need to edit the registry for guidelines configuration anymore.

For Visual Studio 2008 and older, you have to use regedit. Navigate to:

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor

and add a string named Guides with value RGB(0,255,0),80 to create a guideline after column 80. To get more guidelines e.g., after column 80 and 130, set the value to RGB(0,255,0),80,130.

Note: Editor Guidelines extension for VS2010 uses a registry entry similar to the one described above, however its syntax is less strict. I found out on VS2008, that “Guides” string value cannot contain any spaces.

Registry paths for various Visual Studio versions:

2003: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.1\Text Editor
2005: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Text Editor
2008: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor
2008 Express: HKEY_CURRENT_USER\Software\Microsoft\VCExpress\9.0\Text Editor

References

Everything that has a beginning has an end. Well, this is the beginning. I’ve decided to create a place where I could store some code snippets found over the web and my own creations as well.

I’ve always been too shy to publish my own views on various patterns, implementations and other stuff. I guess I’m not coping well with any criticism against my programming skills. I’m not a native English speaker, neither. So why to publish potentially flawed stuff commented with bad English? This was my approach until recently. Yup. It is no more. I’ve made up my mind to give it a try.

BTW, I’m a great fan of StackOverflow.com, and this is my profile profile.

Follow

Get every new post delivered to your Inbox.