Thursday, May 17, 2012
I've used this enum helper from time to time to get an enum value from attributes such as Description and XmlEnumAttribute. Maybe you can find it useful?
public static class EnumEx
{
public static T
GetXmlEnumValue<T>(string name)
{
var type = CheckEnum<T>();
var val = (from f in type.GetFields()
let
attribute = f.GetCustomAttributes(typeof(System.Xml.Serialization.XmlEnumAttribute), true).FirstOrDefault()
as System.Xml.Serialization.XmlEnumAttribute
where
attribute != null
&& attribute.Name
== name
select
(T)f.GetValue(null));
if (val.Count() == 0)
throw new
ArgumentException(string.Format("{0} is not a valid XmlEnumAttribute for {1}",
name, typeof(T).FullName), "name");
return val.First();
}
public static T
GetValueFromDescription<T>(string
description)
{
var type = CheckEnum<T>();
var val = (from f in type.GetFields()
let
attribute = f.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), true).FirstOrDefault()
as System.ComponentModel.DescriptionAttribute
where attribute != null
&&
attribute.Description == description
select (T)f.GetValue(null));
if (val.Count() == 0)
throw new
ArgumentException(string.Format("{0} is not a valid description for {1}",
description, typeof(T).FullName), "description");
return val.First();
}
private static Type CheckEnum<T>()
{
var type = typeof(T);
if (type.IsEnum == false)
throw new
InvalidOperationException(string.Format("{0} is not an
enum", typeof(T)));
return type;
}
}
Wednesday, May 18, 2011
Extension Methods for ToXml and FromXml
Friday, December 10, 2010
I simply DO NOT understand how Microsoft can be this far along with a tool like WCF and it STILL tout it as being an "Enterprise" tool.
For example... The following is a simple xsd schema with a VERY simple data contract that any enterprise would expect an "enterprise system" to be able to handle:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Sample"
targetNamespace="http://tempuri.org/Sample.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/Sample.xsd"
xmlns:mstns="http://tempuri.org/Sample.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="SomeDataElement">
<xs:annotation>
<xs:documentation>This documents the data element. This sure would be nice for consumers to see!</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Description" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
<xs:maxLength value="255"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:all>
<xs:attribute name="IPAddress" use="required">
<xs:annotation>
<xs:documentation>Another explanation! WOW!</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="(([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
An minimal example xml document would be:
<?xml version="1.0"encoding="utf-8" ?>
<SomeDataElementxmlns="http://tempuri.org/Sample.xsd" IPAddress="1.1.168.10">
</SomeDataElement>
With the max example being:
<?xml version="1.0"encoding="utf-8" ?>
<SomeDataElementxmlns="http://tempuri.org/Sample.xsd" IPAddress="1.1.168.10">
<Description>ddd</Description>
</SomeDataElement>
This schema simply CANNOT be exposed by WCF.
Let's list why:
- svcutil.exe will not generate classes for you because it can't read an xsd with xs:annotation.
- Even if you remove the documentation, the DataContractSerializer DOES NOT support attributes so IPAddress would become an element this not meeting the contract
- xsd.exe could generate classes but it is a very legacy tool, generates legacy code, and you still suffer from the following issues:
- NONE of the serializers support emitting of the xs:annotation documentation. You'd think a consumer would really like to have as much documentation as possible!
- NONE of the serializers support the enforcement of xs:restriction so you can forget about the xs:minLength, xs:maxLength, or xs:pattern enforcement.
Microsoft... please, please, please, please look at putting the work into your serializers so that they support the very basics of designing enterprise data contracts!!
Wednesday, September 08, 2010
Below is a multithreaded queue with progress reporting and nice exception handling that I implemented for a project. I hope it might help someone else. You can copy and paste the following code into a console app to see how to use it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
namespace WorkQueueTest
{
class Program
{
static readonly object locker = new object();
static void Main(string[] args)
{
//You can play with these values to test
var workQueueSettings = new {NumberOfTasks = 6, NumberOfTaskSteps = 3, TaskStepSleepTime = 500, NumberOfThreads = 3};
var nonThreadingTime = workQueueSettings.NumberOfTasks * workQueueSettings.NumberOfTaskSteps * workQueueSettings.TaskStepSleepTime;
Console.WriteLine("====================\nWithout a work queue, this would take {0} milliseconds\n====================", nonThreadingTime);
var workQueue = new WorkQueue(workQueueSettings.NumberOfThreads);
var stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < workQueueSettings.NumberOfTasks; i++)
{
var index = i;
workQueue.Enqueue(new WorkItem
{
OnException = OnException,
OnProgressChanged = OnProgressChanged,
Task = onProgressChangedCallBack =>
{
#region - Code to actually do stuff goes here... the rest of this is sample fluff
//
var taskName = "Task #" + index;
//fake some long running process
for (var j = 0; j < workQueueSettings.NumberOfTaskSteps; j++)
{
Thread.Sleep(workQueueSettings.TaskStepSleepTime);
var percent = (int)(((decimal)j / workQueueSettings.NumberOfTaskSteps) * 100);
onProgressChangedCallBack(new ProgressChangedEventArgs(percent, taskName));
}
if (workQueueSettings.NumberOfTasks>2 && index == 2)//fake a sample exception
throw new Exception("Some fake exception.");
onProgressChangedCallBack(new ProgressChangedEventArgs(100, taskName));
#endregion
}
});
}
workQueue.WaitForTasksToComplete();//wait for the tasks to complete before continuing
workQueue.Stop(false);
stopWatch.Stop();
Console.WriteLine("====================\nTotal time = {0} milliseconds\n====================\nPress any key to exit", stopWatch.ElapsedMilliseconds);
Console.ReadLine();
}
private static void OnException(Exception ex)
{
lock (locker)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("EXCEPTION: {0}", ex);
Console.ResetColor();
}
}
private static void OnProgressChanged(ProgressChangedEventArgs eventArgs)
{
lock (locker)
{
switch (eventArgs.ProgressPercentage)
{
case 0:
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Starting {0}", eventArgs.UserState);
break;
case 100:
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Completed 100% of {0}", eventArgs.UserState);
break;
default:
Console.WriteLine("Completed {0} of {1}", eventArgs.ProgressPercentage, eventArgs.UserState);
break;
}
Console.ResetColor();
}
}
}
public class WorkItem
{
public virtual Action<Exception> OnException { get; set; }
public virtual Action<ProgressChangedEventArgs> OnProgressChanged { get; set; }
public virtual Action<Action<ProgressChangedEventArgs>> Task { get; set; }
}
public class WorkQueue
{
private readonly object locker = new object();
private readonly Thread[] threads;
private readonly Queue<WorkItem> queue = new Queue<WorkItem>();
internal class QueueStopWorkItem : WorkItem{}
public WorkQueue(int workerCount)
{
threads = new Thread [workerCount];
// Create and start a separate thread for each worker
for (var i = 0; i < workerCount; i++)
(threads [i] = new Thread (RunWorkItem)).Start();
}
public void Stop (bool waitForWorkersToComplete)
{
if (waitForWorkersToComplete == false)
{
lock (locker)
{
queue.Clear();
}
}
// Enqueue stop worker item for each worker to make each exit.
for (var i = 0; i < threads.Length; i++)
{
Enqueue(new QueueStopWorkItem());
}
// Wait for threads to finish
if (waitForWorkersToComplete)
{
for (var i = 0; i < threads.Length; i++)
{
threads[i].Join();
}
}
}
public void Enqueue (WorkItem workItem)
{
lock (locker)
{
queue.Enqueue(workItem); //Push one element into the queue.
Monitor.Pulse(locker); //Release the waiting thread
}
}
void RunWorkItem()
{
while (true)// loop until a stop work item is found.
{
WorkItem item;
lock (locker)
{
while (queue.Count == 0)
Monitor.Wait(locker); ////Wait, if the queue is busy.
item = queue.Dequeue();
}
if (item is QueueStopWorkItem)
return; // Time to exit.
try
{
item.Task(item.OnProgressChanged); // Execute item.
}
catch(Exception ex)
{
if (item.OnException != null)
item.OnException(ex);
else
throw;
}
}
}
public void WaitForTasksToComplete()
{
Stop(true);
}
}
}
The result should look like the following:
Friday, August 13, 2010
I just released a new project on CodePlex called SimpleWcf"
SimpleWcf provides a way to essentially do “simple, configuration-less, file-less, WCF 4.0”. It works by discovering services using reflection and assumes a convention is intended for the namespaces.
It leverages a lot of the great new baked in defaults in WCF 4.0.
http://simplewcf.codeplex.com/documentation
Thursday, April 01, 2010
I was fighting with this issue today... Visual Studio was taking FOREVER to load the symbol files (.pdb) in order to start debugging. It seems if you clear all of your break points, the issue is corrected. Hope this helps someone.
Wednesday, August 19, 2009
Wow, so I just had to install the JRE for a product and was shocked to see the following:

AND they recommend it!
Hell hath frozen!
Wednesday, June 17, 2009
An extension to JQuery LightBox for max width and height
Thursday, May 28, 2009
Saturday, May 09, 2009
Wednesday, January 14, 2009
So, it took me forever today to figure out how to get
PostSharp working without installing it 'globally' with the msi installer.
In a nutshell, you have to include a directory for example
/lib/ with all of the PostSharp baggage:
- Default.psproj
- PostSharp.targets
- PostSharp-1.0.targets
- PostSharp-1.0.version
- PostSharp-AppDomain.config
- PostSharp-Platform.config
- PostSharp.Core.dll
- PostSharp.Core.pdb*
- PostSharp.Core.XmlSerializers.dll
- PostSharp.exe
- PostSharp.exe.config
- PostSharp.pdb*
- PostSharp.Laos.dll
- PostSharp.Laos.pdb*
- PostSharp.Laos.psplugin
- PostSharp.Laos.Weaver.dll
- PostSharp.Laos.Weaver.pdb*
- PostSharp.MSBuild.dll
- PostSharp.MSBuild.pdb*
- PostSharp.Public.dll
- PostSharp.Public.pdb*
* = Optional
Add a reference to the PostSharp.Laos and PostSharp.Public assemblies in your project.
Then you have to edit your .csproj file around the existing <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> section to be:
<PropertyGroup>
<DontImportPostSharp>True</DontImportPostSharp>
<PostSharpDirectory>lib\</PostSharpDirectory>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(PostSharpDirectory)PostSharp.targets" />
You can download a working demo: http://rapidshare.com/files/183439996/PostSharpTest.zip.html
Monday, November 10, 2008
So I ran into an issue this evening where I needed to map a string property to a NCLOB column but I kept getting:
"ORA-01461: can bind a LONG value only for insert into a LONG column"
Turns out that you should set the column type to "AnsiString" as in:
<property name="Contents" column="CONTENTS" type="AnsiString"/>
- Hope this helps someone else out.
Thursday, October 23, 2008
I needed to be able to call a static method on a generic class today, so I thought I would post it up here to share with the world. Enjoy.
//Our Generic Class
public class SomeGenericClass<T>
{
public static char[] ConvertToCharArray(T something)
{
return something.ToString().ToCharArray();
}
}
The example code:
// Get the type of the generic class
Type typeofClassWithGenericStaticMethod = typeof(SomeGenericClass<>);
//Get a typed version of the generic type
Type type = Type.GetType("System.String");
Type[] args = new[] { type };
Type genericType = typeofClassWithGenericStaticMethod.MakeGenericType(args);
// Get a reference to the method you want to call.
MethodInfo methodInfo = genericType
.GetMethod("ConvertToCharArray", System.Reflection.BindingFlags.Static | BindingFlags.Public);
// Invoke the method with parameters. (If it doesn't have a pameter, use null instead of the object array)
object returnValue = methodInfo.Invoke(null, new object[]{"Hello World"});
char[] characters = (char[])returnValue;
foreach (char character in characters)
{
Console.Write(character);
}
Monday, September 29, 2008
Wow, the ASP.NET MVC team just keeps getting it right!
I am truly shocked that Microsoft is going to take advantage of a well-known, well-tested open source framework instead of trying to (poorly) invent their own... (cough... ASP.NET Ajax)
Scott Gu - jQuery and Microsoft :
http://weblogs.asp.net/scottgu/archive/2008/09/28/jquery-and-microsoft.aspx
Wednesday, December 12, 2007
Visual Studio 2008 & .NET 3.5 Quick Changes Overview
I AM NOT TRYING TO REPRESENT THIS WORK AS MY OWN, I AM MERELY AGGRIGATING EXISTING INFORMATION HERE FOR MY OWN BENIFIT AND MAYBE YOURS
Visual Studio 2008
General
· Can target framework versions 2, 3, and 3.5
· Built in ORM
ASP.NET
· Now supports nested master pages in the designer
· Faster switching between markup and designer
· Split view for seeing the designer and markup at the same time
· Drastically improved CSS support with new “Manage Styles” property window
· ASP.NET AJAX 1.0 is now baked in
· Built in JavaScript intellisense
o C# style code comments for additional information via intellisense
C# Language Changes
· Automatic Properties
o No longer required to have a private member variables and public getter/setters. The compiler figures out what is meant by the new syntax and automatically generates it for you in the resulting IL.
|
Traditional Way
|
New Less Verbose Way
|
|
public class Person
{
private string name;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
}
|
public class Person
{
public string Name { get; set; }
}
|
· Object Initializers
o No longer have to build constructors for every possible way you want to initialize the object.
|
Traditional Way
|
New Less Verbose Way
|
|
public class Person
{
private string name;
public Person()
{
}
public Person(string name)
{
this.name = name;
}
public string Name
{
get { return this.name; }
set { this.name = value; }
}
}
|
public class Person
{
public string Name { get; set; }
}
//*notice no constructors are defined
|
|
Person person = new Person();
person.Name = "Scott";
// -- or –
person.Name = new Person("Scott");
|
Person person = new Person();
person.Name = "Scott";
//-- or –-
person = new Person{Name = "Scott"};
//Note the use of curly braces ^
|
· Collection Initializers
|
List<Person> people = new List<Person>();
people.Add(new Person("Frank"));
people.Add(new Person("Dean"));
people.Add(new Person("Sammy"));
|
List<Person> people = new List<Person> {
new Person { Name = "Scott"}
,new Person { Name = "Bill"}
,new Person { Name = "Susanne"}
};
|
· Extension Methods
o Allows developers to add new methods to existing CLR types.
|
Traditional Way
|
Using Extension Methods
|
|
namespace Validation
{
public static class Validator
{
public static bool IsInt(string s)
{
Regex regex = new Regex(@"^[-+]?\d*$");
return regex.IsMatch(s);
}
}
}
using Validation;
if (Validator.IsInteger(textBox.Text))
{
//Do Something
}
|
namespace LanguageExtensions
{
public static class StringExtensions
{
public static bool IsInt(this string s)
{
Regex regex = new Regex(@"^[-+]?\d*$");
return regex.IsMatch(s);
}
}
}
using LanguageExtensions;
if (textBox.Text.IsInt())
{
//Do Something
}
|
· Anonymous Types
o A variable’s type is inferred from its initialization
|
Traditional Way
|
Using Anonymous Types + Object Initializers
|
|
Person person = new Person();
person.Name = "Scott";
|
var person = new Person{Name="Scott"};
|
· Lambda Expressions
o A less verbose way of accomplishing anonymous methods which were introduced in 2.0
|
Traditional Way
|
Using Lambda Expressions + Anonymous Types
|
|
List<Person> people = new List<Person>();
people.Add(new Person("Bob"));
people.Add(new Person("Bobby"));
people.Add(new Person("Susanne"));
List<Person> filtered = people.FindAll
(
delegate(Person p)
{
return p.Name.StartsWith("Bob");
}
);
|
List<Person> people = new List<Person> {
new Person { Name = "Scott"}
,new Person { Name = "Bill"}
,new Person { Name = "Susanne"}
};
var filtered2 = peeps.FindAll(p => p.Name.StartsWith("Bob"));
|
· LINQ (Language Integrated Query)
o LINQ is the attempt of adding the expressiveness of SQL to .NET languages
|
Traditional Way
|
Using LINQ Query Syntax
|
|
List<Person> results = new List<Person>();
foreach (Person p in people)
{
if(p.Name.StartsWith("Bob"))
{
results.Add(p);
}
}
// -- or –
List<Person> results = people.FindAll
(
delegate(Person p)
{
return p.Name.StartsWith("Bob");
}
);
|
var results =
from p in people
where p.Name.StartsWith("Bob")
select p;
|
o Additional Examples