September 2005 Entries

Aspect Oriented Programming with Spring and Generics

 

I wanted to post this example to flesh out an idea I was thinking about earlier today. Suppose you wanted to check permissions of a user before they made a method call, you might suggest an implementation of code access security. While that's a fair suggestion, I'd like to throw another option into the mix. With aspect oriented programming using the Spring framework, you can effectively check permissions before a method is called through the use of a proxy object that dispatches your calls to interceptors, that subsuquently invoke the requested call. Thus, depending on the results of your permission check, you can decide if you want to call the requested method or not. Here is a quick example implemented with generics. In the example, within the SecurityInterceptor you would check permissions which would allow you to control the Proceed call of the IMethodInvocation interface. Thoughts?

using System;
using
AopAlliance.Intercept;
using
Spring.Aop.Framework;
using
Spring.Aop.Interceptor;

namespace
DeveloperNotes
{
public class SecurityInterceptor : IMethodInterceptor
{

public object Invoke(IMethodInvocation invocation)
{
Console.WriteLine(
"Before: invocation=[{0}]", invocation);
object
rval = invocation.Proceed();
Console.WriteLine("Invocation returned");
return
rval;
}
}

public class ObjectFactory
{
public static K CreateObject<T, K>()
{
T obj
= Activator.CreateInstance<T>();
if
(obj != null)
{
ProxyFactory factory
= new ProxyFactory(obj);
factory.AddAdvice(new SecurityInterceptor());
return
(K)factory.GetProxy();
}
return default(K);
}
}

public interface IPerson
{
string Name
{
get;
set;
}

void SayHello();
}

public class Person : IPerson
{

private string name = string.Empty;

public string
Name
{
get{return name;}
set{name = value;}
}

public void SayHello()
{
Console.WriteLine(
"Hello {0}", this.Name);
}
}

class Program
{
static void Main(string[] args)
{
IPerson p
= ObjectFactory.CreateObject<Person, IPerson>();
if
(p != null)
{
p.Name
= "Nick";
p.SayHello();
}
Console.Read()
;
}
}
}

Quote Of The Day

 

We've been using Visual Studio 2005 for the last two months, including Visual Studio Team Systems for our source control repository. We have enabled the requirement that a comment is required before a check-in can take place. Because this is a beta product we have had our share of issues to work with, though I'm extremely happy with the product. This comment came in today from Javier and I thought it was worth sharing. For those days when you just have no idea what happened, comments like these arise.

“File is unchanged. I needed to check it out so I could bind it to source control. Don't ask me, it's a TS thing.”

Sneak Attack

 

I just came across a post by Neal Ford, a developer at ThoughtWorks describing his successful attempt at implementing an agile, test driven development approach to solving a problem for their customer. Sneak attack was the best way I could put it, but well worth the read.

Internet Explorer Developer Toolbar

 

I just came across this new toolbar, targeted specifically for web developers, release by the IE team. There are a host of different items this toolbar provides such as exploring and modifying the DOM of a web page, getting a report on all images within a web page, validating HTML, CSS, and 508 support for web accessibility. Also there is a really helpful ruler that can measure any element on a site. If you are developing for the web this is an excellent tool.

Extension Methods in C# 3.0

 

Microsoft has made public documention describing new features of C# 3.0. At the PDC today, Microsoft announced LINQ, but there are other features of the C# language that are changing drastically. For example, extension methods are being added to the language which will allow you to do something like the following:

namespace Acme.Utilities
{
public static class Extensions
{
public static int ToInt32(this string s)
{
return Int32.Parse(s);
}

public static T[] Slice(this T[] source, int index, int count)
{
if (index < 0 || count < 0 || source.Length – index < count)
throw new ArgumentException();
T[] result = new T[count];
Array.Copy(source, index, result, 0, count);
return
result;
}
}
}
Assuming you import the Acme.Utilities namespace you can do the following:

string s = "1234";
int
i = s.ToInt32();

int
[] digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int
[] a = digits.Slice(4, 3);

Note, this works simply by marking your method's first parameter with the 'this' keyword, simple as that.

NT Groups in .NET 2.0

 

Yesterday, we needed to get the NT groups associated to an account. I have done this before, but now our team is working in .NET 2.0. It's worth noting that the value for each group returned from the WindowsIdentity is in the form of a SID, or a SecurityIdentifier which we can use to translate into a more human readable form, the NTAccount.

 

WindowsIdentity wi = WindowsIdentity.GetCurrent();
if
(wi != null)
{
foreach(IdentityReference group in wi.Groups)
{
if(group != null)
{
NTAccount acct
= group.Translate(typeof(NTAccount)) as NTAccount;
if
(acct != null)
{
Console.WriteLine(acct.Value)
;
}
}
}
}

MSBuild Context Menu Revisited

 

I mentioned in a previous post how to add a context menu for invoking MSBuild against any .*proj file. The only problem I had was I wasn't able to pass the file name to MSBuild, which would have typically been qualified with "%1" following the MSBuild command. When MSBuild is invoked and a file isn't passed to it, it searches the directory to find one. The problem is, if there are more than one .*proj files in the same directory, it doesn't know which file to run. To solve this, I moved the setting of the environment variables to the AutoRun key of the command prompt, this way, the environment variables are always set. Then I only had to invoke MSBuild from my command entry in which I was able to pass the selected file. Here are the two registry entries needed.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor]
"AutoRun"="\"%VS80COMNTOOLS%vsvars32.bat\""
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell\Run with MSBuild\command]
@="cmd /k msbuild \"%1\""

Advanced Design Time Support For Your Components

 

Have you ever noticed the blue links below the property grid of a objects such as the DataGrid or TabControl when you drag it onto a form? These links provide additional configuration functionality of their objects through various means; a UITypeEditor is used for the DataGrid for example. Implementing this functionality is rather simple, here is just an example.

The follow example will allow you to edit the FullName value through a custom UITypeEditor, exposing the editor several different ways, one of which is a custom designer for the component.

namespace DeveloperNotes
{
using System;
using
System.Drawing;
using
System.Windows.Forms;
using
System.Windows.Forms.Design;
using
System.Drawing.Design;
using
System.ComponentModel;
using
System.ComponentModel.Design;

[Designer(typeof(ManagerDesigner))]
public class ManagerComponent : Component
{
public ManagerComponent(){}

private static string name = string.Empty;

[Editor(typeof(NameEditor), typeof(UITypeEditor))]
public string FullName
{
get{return name;}
set{name = value;}
}
}

internal class ManagerDesigner : ComponentDesigner
{
DesignerVerbCollection verbs
= null;
frmNameEditor editor = null;
ManagerComponent mgr = null;

public
ManagerDesigner(){}
public override void Initialize(IComponent component)
{
mgr
= component as ManagerComponent;
base
.Initialize(component);
}

public override DesignerVerbCollection Verbs
{
get
{
if(verbs == null)
{
verbs
= new DesignerVerbCollection();
DesignerVerb verb = new DesignerVerb("Configure Advanced Functionality",
new EventHandler(ConfigAdvanced));
verbs.Add(verb);
}
return verbs;
}
}

public void ConfigAdvanced(object sender, EventArgs e)
{
if(editor == null)
editor
= new frmNameEditor();

editor.FullName = mgr.FullName;
DialogResult dr = editor.ShowDialog();
if
(dr == DialogResult.OK)
{
mgr.FullName
= editor.FullName;
}
}
}

internal class frmNameEditor : System.Windows.Forms.Form
{
private TextBox txtName = new System.Windows.Forms.TextBox();
private
Button btnOk = new System.Windows.Forms.Button();

public string
FullName
{
get{return txtName.Text;}
set{txtName.Text = value;}
}

public frmNameEditor()
{
this.btnOk.Text = "Ok";
this
.btnOk.Click += new EventHandler(btnOk_Click);
this
.btnOk.Location = new Point(50, 50);
this
.Controls.AddRange(new Control[]{this.btnOk, this.txtName});
}

private void btnOk_Click(object sender, EventArgs e)
{
DialogResult
= DialogResult.OK;
}
}

internal class NameEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
if(context != null)
{
return UITypeEditorEditStyle.Modal;
}
return base.GetEditStyle(context);
}

public override object EditValue(ITypeDescriptorContext context,
IServiceProvider provider,
object value)
{
if((context != null) && (provider != null))
{
IWindowsFormsEditorService editorService
=
provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

if
(editorService != null)
{
frmNameEditor editor
= new frmNameEditor();
editor.FullName = value as string;

if
(editorService.ShowDialog(editor) == DialogResult.OK)
{
return editor.FullName;
}
}
}
return base.EditValue(context, provider, value);
}
}
}

Some Interesting Thoughts On Consulting

 

I came across both these links today and thought they were worth sharing. Let me know what your thoughts are concerning the topic once you have read both links.

IE7 Problem

 

I noticed that following the installation of IE7, Trillian was no longer working. Apparently IE7 is shipping with a new version of wininet.dll which caused the problem. I have since uninstalled IE7 but wanted to note this in case anyone else was running into similar issues.