Removing Duplicate Items from an Abstract Generic List
Posted by Ryan Baxter Thu, 31 Jul 2008 14:40:00 GMT
I’ve got some explaining to do. I
was hesitant in posting this code for fear that it might be too niche
to benefit anyone. It may be, but the underlying problem affects many
programmers working in the IT industry. What do you do when the company
legacy system’s data model doesn’t work with your fancy ORM (Object-relational mapping)?
“Any problem in computer science can be solved with another layer of indirection. But that usually will create another problem.” - David Wheeler
At my last job, the ERP (Enterprise resource planning) system was something of mystery and voodoo. Only a few had sufficient knowledge to work with it and because of its arcane nature it was deemed untouchable. Within my first months as an employee I wrote a rudimentary ORM to serve as a layer between our client applications and the ERP system. Its performance was terrible. I wrote it off as “experience” and the department ultimately decided to ignore interfacing directly with the ERP system.
I’m using the SubSonic ORM on a few ASP.NET projects with my current employer. SubSonic has worked great, but a few of its database requirements have left me in the dust with yet another ERP system. The ERP’s tables have no primary keys, constraints, or relationships, but rather than write a complete ORM I decided to roll my own data layer.
All of the strongly-typed collections in the ERP’s data layer implement the AbstractList type. AbstractList implements List
The IUniqueIdentifier interface contains only one property, UniqueIdentifier.
public interface IUniqueIdentifier
{
string UniqueIdentifier
{
get;
set;
}
}If the ERP system contained a table called Customers a Customer type implementing IUniqueIdentifier would be created.
public class Customer : IUniqueIdentifier
{
private string uniqueIdentifier;
// etc...
public UniqueIdentifier
{
get { return this.uniqueIdentifier; }
set { this.uniqueIdentifier = value; }
}
}I’d also have a CustomerCollection class:
public class CustomerCollection : AbstractList<Customer, CustomerCollection>
{
// etc...
}After such a long-winded introduction I can feel better about dumping the following code on anyone that has happened to read this far (kudos to you).
public abstract class AbstractList<ItemType, ListType> :
List<ItemType> where ItemType:IUniqueIdentifier where
ListType:AbstractList<ItemType, ListType>, new()
{
public ListType RemoveDuplicates()
{
Dictionary<string, int> uniqueStore = new Dictionary<string, int>();
ListType list = new ListType();
foreach (ItemType item in this)
{
if (!uniqueStore.ContainsKey(item.UniqueIdentifier))
{
uniqueStore.Add(item.UniqueIdentifier, 0);
list.Add(item);
}
}
return list;
}
}I’d love to hear how others have worked around legacy systems and still kept their code clean.
- Posted in Code Snippets, Expect the Unexpected
- Meta no trackbacks, no comments, permalink, rss, atom
Temporary Identity Impersonation in ASP.NET
Posted by Ryan Baxter Tue, 27 May 2008 16:01:00 GMT
Uploading files in an ASP.NET application is relatively easy to do. Uploading to a remote machine is a little bit trickier, but certainly doable. I followed a set of instructions on aspalliance.com, but rather than declare an account to impersonate in my web.config file, I decided to do it in code. That way I could use impersonation only when needed and encapsulate it for later use.
I referred to an article on Microsoft’s Help and Support website about how to implement impersonation. Their code worked great, but I decided to put it in a class to help keep things DRY.
using System;
using System.Web;
using System.Web.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;
namespace Utilities
{
public class ImpersonateUser
{
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public bool ImpersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
public void UndoImpersonation()
{
impersonationContext.Undo();
}
}
}After referencing my Utilities namespace I was then able to impersonate the account required for uploading:
if (FileUpload1.HasFile)
{
ImpersonateUser impersonateUser = new ImpersonateUser();
if (impersonateUser.ImpersonateValidUser("userName", "", "password"))
{
FileUpload1.SaveAs(Server.MapPath("~/files/fileName.txt"));
impersonateUser.UndoImpersonation();
}
else
{
throw new Exception("Identity impersonation has failed.");
}
}*The SaveAs method of the FileUpload control requires a root path. Using Server.MapPath will provide the root path of your IIS virtual folder.
- Posted in Code Snippets
- Meta no trackbacks, 3 comments, permalink, rss, atom
Rockscroll Visual Studio Add-in
Posted by Ryan Baxter Tue, 13 May 2008 13:32:00 GMT
Last Friday, Scott Hanselman announced the release of the Rockscroll Visual Studio Add-in. Rockscroll replaces Visual Studio’s code-view scrollbar with a miniature visual representation of your source code. This feature makes navigation in large source files that much easier.
Before Rockscroll, I’d oftentimes make mental notes of the scrollbar’s position while traversing code. That, and when spending a lot of time on a project I’d become so familiar with the source code that I’d begin to recognize most code blocks by shape. Rockscroll provides both of these mnemonic devices, but with less brain work. That is a good thing. Thank you, Rocky Downs. Can I have this in NetBeans? :)
- Meta no comments, permalink, rss, atom

