Posted by timvw on 18 Feb 2010 at 20:09 under C#
A couple of weeks ago i was working on an application that would transfer data through a couple of components as a List<object>. In essence, all we were doing over and over again was the following:
interface IMapper<TEntity>
{
TEntity FromObjectList(List<object> objectList);
List<object> ToObjectList(TEntity entity);
}
My initial implementation (using EnumerableEx operators from Reactive Extensions) looked like this:
public TEntity FromObjectList
(List
<object> objectList
)
{
var entity
= new TEntity
();
properties
.
Zip(objectList,
(property, value
) => AssignValueToProperty
(entity, property, value
))
.
Run();
return entity
;
}
int AssignValueToProperty
(object entity, PropertyInfo property,
object value
)
{
property.
SetValue(entity, value,
null);
return 0;
}
public List
<object> ToObjectList
(TEntity entity
)
{
return properties
.
Select(property
=> property.
GetValue(entity,
null))
.
ToList();
}
And the consumer code looks like this:
var person
= new Person
{ Id
= 2, Score
= 1.3, Name
= "Tim", Title
= "Sir" };
var personMapper
= new Mapper
<Person
>()
.
Map(x
=> x.
Id)
.
Map(x
=> x.
Score)
.
Map(x
=> x.
Name)
.
Map(x
=> x.
Title);
var data
= personMapper.
ToObjectList(person
);
var clonedPerson
= personMapper.
FromObjectList(data
);
Wait a minute, in most situations we simply want to map all properties on the object. Let’s create a mapper for this:
class AutoMapper
<TEntity
> : Mapper
<TEntity
> where TEntity
: new()
{
public AutoMapper
()
{
typeof(TEntity
).
GetProperties().
Run(property
=> Map
(property
));
}
}
And now we don’t have to waste time doing the same thing over and over again! Because we always need to map all properties of our types we ended up with the following:
public static class Mapper
{
public static List
<Object> ToObjectsList
<TEntity
>(this TEntity entity
)
{
return entity.
GetType().
GetProperties()
.
Select(property
=> property.
GetValue(entity,
null))
.
ToList();
}
public static TEntity ToEntity
<TEntity
>(this List
<Object> objectsList
) where TEntity
: new()
{
TEntity entity
= new TEntity
();
entity.
GetType().
GetProperties()
.
Zip(objectsList,
(property, value
) =>{ property.
SetValue(entity, value,
null); return 0;})
.
Run();
return entity
;
}
}
Posted by timvw on 17 Feb 2010 at 19:18 under C#
A couple of weeks ago i discovered Enumerable.OfType<TResult> when i let Resharper rewrite my code as a Linq statement. Here is the original code:
var selectedPersons
= new List
<PersonSelectItem
>();
foreach(var selectedItem
in selectedItems
)
{
var selectedPerson
= selectedItem
as PersonSelectItem
;
if (selectedPerson
== null) continue
;
selectedPersons.
Add(selectedPerson
);
}
And here is how it looks after the rewrite:
var selectedPersons = selectedItems.OfType<PersonSelectItem>().ToList();
Yup, the Resharper license was definitely worth it’s money.
Because Silverlight checks the origin it considers http://localhost and http://127.0.0.1 as different locations. In case you want your visitors to be able to use both addresses you can recalculate the address as following:
EndpointAddress GetEndpointAddress
(EndpointAddress endpointAddress
)
{
var scheme
= Application.
Current.
Host.
Source.
GetComponents(UriComponents.
Scheme, UriFormat.
Unescaped);
var serverAndPort
= Application.
Current.
Host.
Source.
GetComponents(UriComponents.
HostAndPort, UriFormat.
Unescaped);
var pathAndQuery
= endpointAddress.
Uri.
GetComponents(UriComponents.
PathAndQuery, UriFormat.
Unescaped);
return new EndpointAddress
(scheme
+ "://" + serverAndPort
+ pathAndQuery
);
}
And you can use this method as following:
var client
= new DirectoryServiceClient
();
client.
Endpoint.
Address = GetEndpointAddress
(client.
Endpoint.
Address);
client.
GetMessageCompleted += ClientGetMessageCompleted
;
client.
GetMessageAsync();
Posted by timvw on 12 Feb 2010 at 21:50 under C#
In my current project i use TemplateFileTask (MSBuild Community Tasks Project) to generate configuration files. I ran into the problem that i don’t want to expose a MEX endpoint in production. This is my initial template file:
<service behaviorConfiguration="DemoBehavior" name="DemoService.FileService">
<endpoint address="" binding="ws2007HttpBinding" contract="DemoService.IFileService" />
${MexEndpoint}
</service>
And here is my initial msbuild task:
<Project ToolsVersion="3.5" DefaultTargets="GenerateConfigFiles" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<Target Name="GenerateConfigFiles">
<PropertyGroup>
<MexEndpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</MexEndpoint>
</PropertyGroup>
<PropertyGroup Condition=" ‘$(Env)’==’Production’ ">
<MexEndpoint></MexEndpoint>
</PropertyGroup>
<ItemGroup>
<Tokens Include="MexEndpoint">
<ReplacementValue>$(MexEndpoint)</ReplacementValue>
</Tokens>
</ItemGroup>
<TemplateFile Template="Web.template.config" OutputFileName="Web.config" Tokens="@(Tokens)" />
</Target>
</Project>
This results in the following configuration file: (WCF does not like the xml namespace declaration):
<service behaviorConfiguration="DemoBehavior" name="DemoService.FileService">
<endpoint address="" binding="ws2007HttpBinding" contract="DemoService.IFileService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
</service>
I noticed that a smart collegue of mine, Sam Verschooten came up with the following template file:
<service behaviorConfiguration="DemoBehavior" name="DemoService.FileService">
<endpoint address="" binding="ws2007HttpBinding" contract="DemoService.IFileService" />
<${MexBegin}endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /${MexEnd}>
</service>
And this is how he defines the MexBegin and MexEnd properties in msbuild:
<PropertyGroup>
<MexBegin></MexBegin>
<MexEnd></MexEnd>
</PropertyGroup>
<PropertyGroup Condition=" ‘$(Env)’==’Production’ ">
<MexBegin>!–</MexBegin>
<MexEnd>–</MexEnd>
</PropertyGroup>
This leads to a nice MEX endpoint for all environments and in Production we get the following:
<!–endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /–>
Perhaps it is cleaner to implement my own TemplateFileTask but untill then this clever hack does the job
Posted by timvw on 10 Feb 2010 at 19:29 under C#
Currently there are two overloads for OrderBy on Enumerable:
- OrderBy(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
- OrderBy(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
Because i don’t want to implement an IComparer<TKey> each time i have implemented the following class:
class DelegateComparer<T> : IComparer<T>
{
public Func<T, T, int> CompareFunction { get; set; }
public DelegateComparer(Func<T, T, int> compareFunction)
{
CompareFunction = compareFunction;
}
public int Compare(T x, T y)
{
return CompareFunction(x, y);
}
}
And now i can define a nice extension method:
public static IOrderedEnumerable
<TSource
> OrderBy
<TSource, TKey
>(this IEnumerable
<TSource
> source, Func
<TSource, TKey
> keySelector, Func
<TKey, TKey,
int> compareFunction
)
{
var comparer
= new DelegateComparer
<TKey
>(compareFunction
);
return source.
OrderBy(keySelector, comparer
);
}
Posted by timvw on 02 Feb 2010 at 19:39 under C#
Here is another method that earned it’s place in my ever growing toolbox:
public static bool CanDoKeyExchange(this X509Certificate2 certificate)
{
if (!certificate.HasPrivateKey) return false;
var privateKey = certificate.PrivateKey as RSACryptoServiceProvider;
if (privateKey == null) return false;
var canDoKeyExchange = privateKey.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange;
return canDoKeyExchange;
}
Posted by timvw on 28 Jan 2010 at 19:27 under C#, Patterns
Here is a base class for some code that i have written once too many in my life: (In case you’re an early adaptor (.Net 4.0) you may want to use System.Tuple<T1> as base class)
public class ValueType<T> : IComparable, IComparable<ValueType<T>>, IEquatable<ValueType<T>>
where T : IComparable<T>
{
protected T Value { get; private set; }public ValueType(T value)
{
Value = value;
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override string ToString()
{
return Value.ToString();
}
public override bool Equals(object obj)
{
return Equals(obj as ValueType<T>);
}
public bool Equals(ValueType<T> other)
{
return Compare(this, other) == 0;
}
public int CompareTo(object obj)
{
return CompareTo(this, obj as ValueType<T>);
}
public int CompareTo(ValueType<T> other)
{
return Compare(this, other);
}
static int Compare(ValueType<T> instance1, ValueType<T> instance2)
{
if (ReferenceEquals(instance1, instance2)) return 0;
if (ReferenceEquals(instance1, null)) return -1;
if (ReferenceEquals(instance2, null)) return 1;
if (ReferenceEquals(instance1.Value, instance2.Value)) return 0;
if (ReferenceEquals(instance1.Value, null)) return -1;
if (ReferenceEquals(instance2.Value, null)) return 1;
return instance1.Value.CompareTo(instance2.Value);
}
public static bool operator ==(ValueType<T> instance1, ValueType<T> instance2)
{
return Compare(instance1, instance2) == 0;
}
public static bool operator !=(ValueType<T> instance1, ValueType<T> instance2)
{
return !(instance1 == instance2);
}
public static bool operator <(ValueType<T> instance1, ValueType<T> instance2)
{
return Compare(instance1, instance2) < 0;
}
public static bool operator >(ValueType<T> instance1, ValueType<T> instance2)
{
return Compare(instance1, instance2) > 0;
}
}
An Event Aggregator is an example of a Publish/Subscribe channel. A while ago i started wondering if we still need an Event Aggregator in our compisite applications if we have an IOC container that takes cares of dependency wiring. An IOC container can easily inject the Event/MessageHandler(s) in the Event/MessagePublisher(s)… I’m still not sure about the answer (Yes/No).
This weekend i noticed a couple of posts by Uncle Bob trying to get some discussions going. In Mocking Mocking and Testing Outcomes at some point he generates a fake of some class
“Oh, ick!” you say. Yes, I agree it’s a lot of code. On the other hand, it took me just a single keystroke on my IDE to generate all those dummy methods. (In IntelliJ it was simply command-I to implement all unimplemented methods.) So it wasn’t particularly hard. And, of course, I can put this code somewhere where nobody had to look at it unless they want to. It has the advantage that anybody who knows Java can understand it, and can look right at the methods to see what they are returning. No “special” knowledge of the mocking framework is necessary.
So adding a lot of generated code, which no-one should ever look at, is better than a mocking framework? Hahaha, why would i want to repeat myself creating all those fake objects? (DRY)
Another problem that i have with his example is the fact that the ‘dependency’ has a ton of methods that are not used by the consumer, so it makes me wonder: why are those methods there? Define an interface for the required methods, and have your consumer use that interface instead. This way you don’t have to look at those unused methods which only clutter the API.
A second read made it clear that Uncle Bob is talking about unit-tests, which are typically implemented as state-based tests. In case you’re doing integration tests, you will have (more) dependencies and want to verify the interaction between your system under test and the dependencies. And that is (imho) the scenario where mocking frameworks really shine
if you need typemock your design is wrong.
Although i understand what people are trying to say with that quote, it’s wrong on many levels. I pretty much agree with everything that Roy wrote in Test driven design – Willed vs. Forced Designs. As some commenters pointed out it is hard to convince management that they need an isolation framework, let alone that they have to pay for one.
A couple of thoughts:
- What about Pex Stubs & Moles? It uses the profiling API (less limitations than rhino/moq/…) too and for a lot of shops doing .Net development it’s free.
- I really don’t understand people that are unwilling to pay for tools that can contribute to the generation of business value (eg: Resharper, NCover, NDepend, …) when they don’t come from Microsoft.
- Filling up gaps in the .Net/Microsoft space seems like an awful business model.