exports vs module.exports in node.js

I was confused about how require function works in node.js for a long time. I found when I require a module, sometimes I can get the object I want, but sometimes, I don’t I just got an empty object, which give an imagination that we cannot export the object by assigning it to exports, but it seems somehow we can export a function by assignment.

Today, I re-read the document again, and I finally make clear that I misunderstood the “require” mechanism and how I did that.

I clearly remember this sentence in the doc

In particular module.exports is the same as the exports object.

So I believed that the exports is just a shortcut alias to module.exports, we can use one instead of another without worrying about the differences between them two.
But this understanding is proved to be wrong. exports and module.exports are different.

Today I found this in the doc:

The exports object is created by the Module system. Sometimes this is not acceptable, many want their module to be an instance of some class. To do this assign the desired export object to module.exports.

So it says that module.exports is different from exports. And it you exports something by assignment, you need to assign it to module.exports.

Let’s try to understand these sentences deeper by code examples.

In the saying

The exports object is created by the Module system.

The word “created by” actually means when node.js try to load a javascript file, before executing any line of code in your file, the module system executes the following code first for you:

1
var exports = module.exports

So the actual interface in node.js’s module system is module object. the actual exported object is module.exports not exports.
And the exports is just a normal variable, and there is not “magic” in it. So if you assign something to it, it is replaced absolutely.

That’s why I failed to get the exported object I want when I assign the it to exports variable.

So to export some variable as a whole, we should always assign it to module.exports.
And at same time, if there is no good excuse, we’d better to keep the convention that exports is the shortcut alias to module.exports. So we should also assign the module.exports to exports.

As a conclusion, to export something in node.js by assignment, we should always follow the following pattern:

1
2
3
exports = module.exports = {
...
}

Powershell script to serialize and deserialize hash-object to and from ini-like text

Powershell and .net fx provides a dozen of approaches to manipulate hash-object. And it is really easy and convenient to initialize hash-object with values from environment variables, registry or cli arguments.
And Hash-Object can be accessed and built into hierarchy easily, so to use powershell hash-object as deploy configuration is really powerful and convenient.

But in our system, the application uses the ini-like key-value pair plain text as the initial configuration file. So our deploy script need the ability to serialize and deserialize hash-object to and from ini-like config.

So I composed this piece of script.

Powershell Script for Environment Provision and Auto Deploy

I’ve been working on MetaPaas project for a while. And composing deploy script is one of the my major tasks.
Here are some script snippets I found or I compose, which could be very useful in my daily work.

Download File from Web

This piece of script is useful when the script need to download package from CI server or configuration from configuration server etc.
Especially when wget or curl available.

NOTICE: This piece of script enable you to download the file from web in Powershell without any 3rd party dependences. But its performance is not as good as wget. Wget is still recommended if there are quite a lot of files to be downloaded.

Original Source

Get-WebFile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
## Get-WebFile (aka wget for PowerShell)
##############################################################################################################
## Downloads a file or page from the web
## History:
## v3.6 - Add -Passthru switch to output TEXT files
## v3.5 - Add -Quiet switch to turn off the progress reports ...
## v3.4 - Add progress report for files which don't report size
## v3.3 - Add progress report for files which report their size
## v3.2 - Use the pure Stream object because StreamWriter is based on TextWriter:
## it was messing up binary files, and making mistakes with extended characters in text
## v3.1 - Unwrap the filename when it has quotes around it
## v3 - rewritten completely using HttpWebRequest + HttpWebResponse to figure out the file name, if possible
## v2 - adds a ton of parsing to make the output pretty
## added measuring the scripts involved in the command, (uses Tokenizer)
##############################################################################################################
function Get-WebFile {
param(
$url = (Read-Host "The URL to download"),
$fileName = $null,
[switch]$Passthru,
[switch]$quiet
)
$req = [System.Net.HttpWebRequest]::Create($url);
$res = $req.GetResponse();
if($fileName -and !(Split-Path $fileName)) {
$fileName = Join-Path (Get-Location -PSProvider "FileSystem") $fileName
}
elseif((!$Passthru -and ($fileName -eq $null)) -or (($fileName -ne $null) -and (Test-Path -PathType "Container" $fileName)))
{
[string]$fileName = ([regex]'(?i)filename=(.*)$').Match($res.Headers["Content-Disposition"] ).Groups[1].Value
$fileName = $fileName.trim("\/""'")
if(!$fileName) {
$fileName = $res.ResponseUri.Segments[-1]
$fileName = $fileName.trim("\/")
if(!$fileName) {
$fileName = Read-Host "Please provide a file name"
}
$fileName = $fileName.trim("\/")
if(!([IO.FileInfo]$fileName).Extension) {
$fileName = $fileName + "." + $res.ContentType.Split(";")[0].Split("/")[1]
}
}
$fileName = Join-Path (Get-Location -PSProvider "FileSystem") $fileName
}
if($Passthru) {
$encoding = [System.Text.Encoding]::GetEncoding($res.CharacterSet )
[string]$output = ""
}
if($res.StatusCode -eq 200) {
[int]$goal = $res.ContentLength
$reader = $res.GetResponseStream()
if($fileName) {
$writer = new-object System.IO.FileStream $fileName, "Create"
}
[byte[]]$buffer = new-object byte[] 4096
[int]$total = [int]$count = 0
do
{
$count = $reader.Read($buffer, 0, $buffer.Length);
if($fileName) {
$writer.Write($buffer, 0, $count);
}
if($Passthru){
$output += $encoding.GetString($buffer,0,$count)
} elseif(!$quiet) {
$total += $count
if($goal -gt 0) {
Write-Progress "Downloading $url" "Saving $total of $goal" -id 0 -percentComplete (($total/$goal)*100)
} else {
Write-Progress "Downloading $url" "Saving $total bytes..." -id 0
}
}
} while ($count -gt 0)
$reader.Close()
if($fileName) {
$writer.Flush()
$writer.Close()
}
if($Passthru){
$output
}
}
$res.Close();
if($fileName) {
ls $fileName
}
}

Extract File with Windows Explorer

This piece of code enable you to extract zip package without any 3rd party dependencies. It is useful environment provision script, which is usually executed on a Windows without anything being installed.

Extract-Zip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Function Extract-Zip ([string] $zipPath, [string]$destination) {
$progressbar = 4
$shellApplication = New-Object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipPath)
$destinationFolderName = Join-Path $destination "tiger"
if (Test-Path $destinationFolderName ) {
Remove-Item $destinationFolderName -Recurse -Force
}
New-Item $destinationFolderName -type directory
$destinationFolder = $shellApplication.NameSpace($destinationFolderName)
$destinationFolder.CopyHere($zipPackage.Items(), $progressbar)
}

Interpolate value into configuration

This piece of script enable you to replace the place-holders in configuration text with actual values.

Apply-Config
1
2
3
4
5
6
7
8
9
10
Function Apply-Config([hashtable]$config) {
foreach($line in $input) {
foreach($key in $config.Keys) {
$line = $line -replace $key, $config[$key]
}
$line
}
}

This piece of script can be used in different scenarios:

Prepare Configuration

Config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$configuration = @{
"initialCatalog" = "lion"
"logInitialCatalog" = "lion_log"
"webServers" = @("192.168.122.46")
"dbServer" = "192.168.122.65"
"SQLServerDataDir" = "C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA"
"SQLServerDataFileSize" = "10MB"
"dataset" = "prod"
"appPoolUser" = "$($env:COMPUTERNAME)\Lion"
"appPoolPassword" = "1zhlmcl..oostp"
"createAppPoolUser" = $true
}

Apply config to in-memory configuration template

Apply config to string in memory
1
2
3
$configurationText = $configurationTemplate | Apply-Config($configuration)

Create configuration file according to template

Apply config to file
1
2
3
cat $configurationTemplateFile | Apply-Config($configuration) > $configurationFile

Download and apply configuration from configuration server

Download and apply config
1
2
3
Get-WebFile -url $configTemplateUrl -Passthru | Apply-Config($configuration) > $configurationFile

A way to expose singleton object and its constructor in node.js

In Node.js world, we usually encapsulate a service into a module, which means the module need to export the façade of the service. In most case the service could be a singleton, all apps use the same service.

But in some rare cases, people might would like to create several instances of the service ,which means the module also need to also export the service constructor.

A very natural idea is to export the default service, and expose the constructor as a method of the default instance. So we could consume the service in this way:

Ideal Usage
1
2
var defaultService = require('service');
var anotherService = service.newService();

So we need to write the module in this way:

Ideal Export
1
2
3
4
5
function Service() { }
module.exports = new Service();
moudle.exports.newService = Service;

But for some reason, node.js doesn’t allow module to expose object by assigning the a object to module.exports.
To export a whole object, it is required to copy all the members of the object to moudle.exports, which drives out all kinds of tricky code.

I misunderstood how node.js require works, and HERE is the right understanding. Even I misunderstood the mechanism, but the conclusion of this post is still correct. To export function is still a more convenient way to export both default instance and the constructor.

And things can become much worse when there are backward reference from the object property to itself.
So to solve this problem gracefully, we need to change our mind.
Since it is proved that it is tricky to export a object, can we try to expose the constructor instead?

Then answer is yes. And Node.js does allow we to assign a function to the module.exports to exports the function.
So we got this code.

Export Constructor
1
2
function Service() { }
module.exports = Service;

So we can use create service instance in this way:

Create Service
1
2
var Service = require('service');
var aService = new Service();

As you see, since the one we exported is constructor so we need to create a instance manually before we can use it. Another problem is that we lost the shared instance between module users, and it is a common requirement to share the same service instance between users.

How to solve this problem? Since as we know, function is also kind of object in javascript, so we can kind of add a member to the constructor called default, which holds the shared instance of the service.

This solution works but not in a graceful way! A crazy but fancy idea is that can we transform the constructor itself into kind of singleton instance??!! Which means you can do this:

Export Singleton
1
2
3
4
var defaultService = require('service');
defaultService.foo();
var anotherService = service();
anotherService.foo();

The code style looks familiar? Yes, jQuery, and many other well-designed js libraries are designed to work in this way.
So our idea is kind of feasible but how?

Great thank to Javascript’s prototype system (or maybe SELF’s prototype system is more accurate.), we can simply make a service instance to be the constructor’s prototype.

Actual Export
1
2
3
function Service() { }
module.exports = Service;
Service.__proto__ = new Serivce;

Sounds crazy, but works, and gracefully! That’s the beauty of Javascript.

Enhanced typeof() operator in JavaScript

Javascript is weakly typed, and its type system always behaves different than your expectation.
Javascript provide typeof operator to test the type of a variable. it works fine generally. e.g.

typeof default behaviors
1
2
3
4
5
6
typeof(1) === 'number'
typeof('hello') === 'string'
typeof({}) === 'object'
typeof(function(){}) === 'function'

But it is not enough, it behaves stupid when you dealing with objects created by constructors. e.g.
if you expected

Expected typeof behavior against object
1
typeof(new Date('2012-12-12')) === 'date' // Returns false

Then you must be disappointed, since actually
Actual typeof behavior against object
1
typeof(new Date('2012-12-12')) === 'object' // Returns true

Yes, when you apply typeof() operator on any objects, it just yield the general type “object” rather than the more meaningful type “date”.

How can we make the typeof() operator works in the way as we expected?
As we know when we create a object, the special property of the object constructor will be set to the function that create the object. which means:

Get constructor property of object
1
(new Date('2012-1-1')).constructor // Returns [Function Date]

So ideally we can retrieve the name of the function as the type of the variable. And to be compatible with javascript’s native operator, we need to convert the name to lower case. So we got this expression:

Simulate typeof operator behavior with constructor property
1
2
3
4
5
function typeOf(obj) { // Use capital O to differentiate this function from typeof operator
return obj ? obj.constructor.name.toLowerCase() : typeof(obj);
}
typeOf(new Date('2012-1-1')) === 'date' // Returns true

And luckily, we can also apply this to other primitive types, e.g:

Apply typeOf to primitive types
1
2
3
typeOf(123) === 'number'; // Returns true
typeOf('hello') === 'string'; // Returns true
typeOf(function(){}) === 'function'; // Returns true

or even

Apply typeOf to anonymous object
1
typeOf({}) === 'object'; // Returns true

So in general, we use this expression as new implementation of the typeof() operator! EXCEPT One case!

If someone declare the object constructor in this way, our new typeof() implementation will work improperly!

Closure encapsulated anonymous constructor
1
2
3
4
5
var SomeClass = (function() {
return function() {
this.someProperty='some value';
}
})();

or even define the constructor like this

Anonymous Closure
1
2
3
var SomeClass = function() {
this.someProperty = 'some value';
}

And we will find that

Apply typeOf to object instantiated by anonymous constructor
1
typeOf(new SomeClass) === ''; // Returns true

the reason behind this is because the real constructor of the SomeClass is actually an anonymous function, whose name is not set.

To solve this problem, we need to declare the name of the constructor:

Closure encapsulated named constructor
1
2
3
4
5
var SomeClass = (function() {
return function SomeClass() {
this.someProperty='some value';
}
})();

or even define the constructor like this

Named constructor
1
2
3
var SomeClass = function SomeClass() {
this.someProperty = 'some value';
}

Distribute files to multiple servers via scp

The most common task when operating the servers is to distribute a file to multiple servers.
So I wrote a piece of shell script to solve this problem:

mscp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
echo "mscp <source file> <target dir>"
SourceFile=$1
TargetDir=$2
echo "Copy $SourceFile to $TargetDir as $RemoteUser"
echo "Enter the servers:"
if [-f $SourceFile ]
then
printf "File found, preparing to transfer\n"
while read server
do
scp -p $SourceFile ${server}:$TargetDir
done
else
printf "File \"$SourceFile\"not found\n"
exit 1
fi
exit 0

call the script mscp <source file> <target dir>, then the script will ask you the list of target servers. So you can type them one by one. If the remote user is different than you current user, you can also explicitly identify it by typeing user@server

Beside the previous scenario, there is a more common sceanrio, that you have got a server list stored in afile already. Then instead of type the servers line by line, you can pipe the file content to the script.
e.g:

Read server list from file
1
cat server_list.txt > mscp src_files dest_path

HTML codes to put special characters on your Web page

尝试了一下用 LinqPad 把各种诡异的字母转成 Html 编码~结果发现不是左右字符都能转过去~
.net 内置的工具并不能完美的处理所有的 Html 编码~

字符来源

Query

Get html escaped unicodes
1
2
3
"A,a,À,à,Á,á,Â,â,Ã,ã,Ä,ä,Å,å,Ā,ā,Ă,ă,Ą,ą,Ǟ,ǟ,Ǻ,ǻ,Æ,æ,Ǽ,ǽ,B,b,Ḃ,ḃ,C,c,Ć,ć,Ç,ç,Č,č,Ĉ,ĉ,Ċ,ċ,D,d,Ḑ,ḑ,Ď,ď,Ḋ,ḋ,Đ,đ,Ð,ð,DZ,dz,DŽ,dž,E,e,È,è,É,é,Ě,ě,Ê,ê,Ë,ë,Ē,ē,Ĕ,ĕ,Ę,ę,Ė,ė,Ʒ,ʒ,Ǯ,ǯ,F,f,Ḟ,ḟ,ƒ,ff,fi,fl,ffi,ffl,ſt,G,g,Ǵ,ǵ,Ģ,ģ,Ǧ,ǧ,Ĝ,ĝ,Ğ,ğ,Ġ,ġ,Ǥ,ǥ,H,h,Ĥ,ĥ,Ħ,ħ,I,i,Ì,ì,Í,í,Î,î,Ĩ,ĩ,Ï,ï,Ī,ī,Ĭ,ĭ,Į,į,İ,ı,IJ,ij,J,j,Ĵ,ĵ,K,k,Ḱ,ḱ,Ķ,ķ,Ǩ,ǩ,ĸ,L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ,Ŀ,ŀ,Ł,ł,LJ,lj,M,m,Ṁ,ṁ,N,n,Ń,ń,Ņ,ņ,Ň,ň,Ñ,ñ,ʼn,Ŋ,ŋ,NJ,nj,O,o,Ò,ò,Ó,ó,Ô,ô,Õ,õ,Ö,ö,Ō,ō,Ŏ,ŏ,Ø,ø,Ő,ő,Ǿ,ǿ,Œ,œ,P,p,Ṗ,ṗ,Q,q,R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř,ɼ,S,s,Ś,ś,Ş,ş,Š,š,Ŝ,ŝ,Ṡ,ṡ,ſ,ß,T,t,Ţ,ţ,Ť,ť,Ṫ,ṫ,Ŧ,ŧ,Þ,þ,U,u,Ù,ù,Ú,ú,Û,û,Ũ,ũ,Ü,ü,Ů,ů,Ū,ū,Ŭ,ŭ,Ų,ų,Ű,ű,V,v,W,w,Ẁ,ẁ,Ẃ,ẃ,Ŵ,ŵ,Ẅ,ẅ,X,x,Y,y,Ỳ,ỳ,Ý,ý,Ŷ,ŷ,Ÿ,ÿ,Z,z,Ź,ź,Ž,ž,Ż,ż"
.Split(',')
.ToDictionary(k=>k,HttpUtility.HtmlEncode)

Result

Dictionary<String,String>
(304 items)



















































































































































































































































































































KeyValue
AA
aa
À&#192;
à&#224;
Á&#193;
á&#225;
Â&#194;
â&#226;
Ã&#195;
ã&#227;
Ä&#196;
ä&#228;
Å&#197;
å&#229;
ĀĀ
āā
ĂĂ
ăă
ĄĄ
ąą
ǞǞ
ǟǟ
ǺǺ
ǻǻ
Æ&#198;
æ&#230;
ǼǼ
ǽǽ
BB
bb
CC
cc
ĆĆ
ćć
Ç&#199;
ç&#231;
ČČ
čč
ĈĈ
ĉĉ
ĊĊ
ċċ
DD
dd
ĎĎ
ďď
ĐĐ
đđ
Ð&#208;
ð&#240;
DZDZ
dzdz
DŽDŽ
dždž
EE
ee
È&#200;
è&#232;
É&#201;
é&#233;
ĚĚ
ěě
Ê&#202;
ê&#234;
Ë&#203;
ë&#235;
ĒĒ
ēē
ĔĔ
ĕĕ
ĘĘ
ęę
ĖĖ
ėė
ƷƷ
ʒʒ
ǮǮ
ǯǯ
FF
ff
ƒƒ
GG
gg
ǴǴ
ǵǵ
ĢĢ
ģģ
ǦǦ
ǧǧ
ĜĜ
ĝĝ
ĞĞ
ğğ
ĠĠ
ġġ
ǤǤ
ǥǥ
HH
hh
ĤĤ
ĥĥ
ĦĦ
ħħ
II
ii
Ì&#204;
ì&#236;
Í&#205;
í&#237;
Î&#206;
î&#238;
ĨĨ
ĩĩ
Ï&#207;
ï&#239;
ĪĪ
īī
ĬĬ
ĭĭ
ĮĮ
įį
İİ
ıı
IJIJ
ijij
JJ
jj
ĴĴ
ĵĵ
KK
kk
ĶĶ
ķķ
ǨǨ
ǩǩ
ĸĸ
LL
ll
ĹĹ
ĺĺ
ĻĻ
ļļ
ĽĽ
ľľ
ĿĿ
ŀŀ
ŁŁ
łł
LJLJ
ljlj
MM
mm
NN
nn
ŃŃ
ńń
ŅŅ
ņņ
ŇŇ
ňň
Ñ&#209;
ñ&#241;
ʼnʼn
ŊŊ
ŋŋ
NJNJ
njnj
OO
oo
Ò&#210;
ò&#242;
Ó&#211;
ó&#243;
Ô&#212;
ô&#244;
Õ&#213;
õ&#245;
Ö&#214;
ö&#246;
ŌŌ
ōō
ŎŎ
ŏŏ
Ø&#216;
ø&#248;
ŐŐ
őő
ǾǾ
ǿǿ
ŒŒ
œœ
PP
pp
QQ
qq
RR
rr
ŔŔ
ŕŕ
ŖŖ
ŗŗ
ŘŘ
řř
ɼɼ
SS
ss
ŚŚ
śś
ŞŞ
şş
ŠŠ
šš
ŜŜ
ŝŝ
ſſ
ß&#223;
TT
tt
ŢŢ
ţţ
ŤŤ
ťť
ŦŦ
ŧŧ
Þ&#222;
þ&#254;
UU
uu
Ù&#217;
ù&#249;
Ú&#218;
ú&#250;
Û&#219;
û&#251;
ŨŨ
ũũ
Ü&#220;
ü&#252;
ŮŮ
ůů
ŪŪ
ūū
ŬŬ
ŭŭ
ŲŲ
ųų
ŰŰ
űű
VV
vv
WW
ww
ŴŴ
ŵŵ
XX
xx
YY
yy
Ý&#221;
ý&#253;
ŶŶ
ŷŷ
ŸŸ
ÿ&#255;
ZZ
zz
ŹŹ
źź
ŽŽ
žž
ŻŻ
żż

FluentAssertion is not compatible with xUnit.Extensions

I met a weird problem that I found the Resharper Test Runner hangs when I introduced theory test case in my unit test.
After some spikes, I found the problem seems caused by the incompatibility between Fluent Assertion and xUnit.Extension.
It is wired, and there seems to be no quick fix.
So I replace the Fluent Assertion with Should and Should.Fluent, which is a port of ShouldIt.
After that, everything goes well except the syntax between Fluent Assertion and Should Fluent are not compatible with each other, although they’re really similar.
But Should.Fluent doesn’t support something.Should.Be(), it requires something.Should.Be.Equals(), which is really annoying to me.

According to the Fluent’s introduction, Fluent is a direct fork of xUnit. And I’m not sure what’s the impact caused by this.

Push Data Flow Model in C# 4.0

In the pre 4.0 era, there are two interfaces reveal a new world to .net world. The two hero are IEnumerable<T> and IEnumerator<T>.
Based on these two interfaces, .net introduced a lot of amazing staffs that dramatically simplified the development related to data flow, these well known features are: foreach loop, yield keyword, and LINQ.
These 2 interfaces provide an common abstraction layer for the operation that pull data from the data source. And with this abstraction, you can apply foreach loop to almost every kind of data source in the .net world.
IEnumerable<T> and IEnumerator<T> are cool, but they are somehow not so convenient to use in some cases, such as in asynchronous context or in obvious latency environment.
And the pull data flow model also has a capable brother, the push data flow, which can fill up the gap that pull model left for us.

So in .net 4.0, Microsoft introduce another 2 great interfaces, called IObservable<T> and IObserver<T>. These two interfaces, just as IEnumerable<T> and IEnumerator<T>, also open a door to the new world for every .net developer. With these 2 interfaces, people can setup a lot of features that corresponding to IEnumerable<T> and IEnumerator<T>.

Now Microsoft has a great library that called Rx(which stands for “Reactive Extension”), which provided a lot of features that similar to LINQ and more based on IObserable<T> and IObserver<T>.

Sync Notify Pattern for WPF Cross Thread View Model

WPF has a powerful data binding mechanism, by which it is easy to implement MVVM and MVC pattern for UI application.
But thing gets not so beautiful once you introduced multi-thread into the app. Somehow, it means you have to manually call dispatcher method to synchronize the thread context, or else INotifyPropertyChanged contract causes cross thread violation, which is likely to drive UI component throw exception. But tons of calls to Dispatcher.Invoke or Dispatcher.BeginInvoke make you code ugly and hard to maintain. And it is boring to call dispatcher every time you try to write view model properties.

Is there any solution to this embarrassed situation?
The answer is Sync Notify pattern.

By analyzing the WPF data binding data flow, you can find the best point to behave the thread synchronization is at the boundary of your code and WPF implementation, which is the property changed event raiser. To sync the thread context here makes your code clean and effective.

Typically, you might implement the INotifyPropertyChanged in following way:

INofityPropertyChanged Implementation
1
2
3
4
5
6
7
8
9
10
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void Notify(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion

And you might implement the property of view model as following:

Notify Property Decalration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#region Notify Property ViewModelProperty
private string viewModelPropertyBackField;
public string ViewModelProperty
{
get { return viewModelPropertyBackField; }
set
{
if (viewModelPropertyBackField == value)
return;
viewModelPropertyBackField = value;
Notify("ViewModelProperty");
}
}
#endregion

This implementation works perfect in single thread context , but fails in multi-thread context. So we introduce a new event raiser implementation, which synchronize the thread context before raising the event:

SyncNotify
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#region Sync INotifyPropertyChanged Members
protected void SyncNotify(string propertyName, bool wait = false, Dispatcher dispatcher = null)
{
if (PropertyChanged == null)
return;
dispatcher = dispatcher ?? System.Windows.Threading.Dispatcher.CurrentDispatcher;
if (dispatcher.Thread == Thread.CurrentThread)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
else
{
if (wait)
{
dispatcher.Invoke(PropertyChanged, this, new PropertyChangedEventArgs(propertyName));
}
else
{
dispatcher.BeginInvoke(PropertyChanged, this, new PropertyChangedEventArgs(propertyName));
}
}
}
#endregion

This method check the whether it is running on the same thread as dispatcher, it not it synchronize the thread. It works perfect in most common cases.
But this implementation requires you to add some new code to the view model, and requires the event works as a delegate. This restriction sometime hurt, such as when you try to derive your view model from ObservableCollection<T>.
ObservableCollection<T> declared PropertyChanged event, but implemented it explicitly, which means you won’t be able to raise the event by calling PropertyChanged directly. Instead, you need to call protected method OnPropertyChanged.

In such cases, you need the following implementation powered by extension method:

SyncNotifyExtension
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
public static class SyncNotifyExtension
{
public static void SyncNotify(this INotifyPropertyChanged host, string propertyName, Action<PropertyChangedEventArgs> eventRaiser, bool wait = false, Dispatcher dispatcher = null)
{
Contract.Requires<ArgumentNullException>(host != null);
Contract.Requires<ArgumentException>(string.IsNullOrWhiteSpace(propertyName));
Contract.Requires<ArgumentNullException>(eventRaiser != null);
dispatcher = dispatcher ?? System.Windows.Threading.Dispatcher.CurrentDispatcher;
if (dispatcher.Thread == Thread.CurrentThread)
{
eventRaiser(new PropertyChangedEventArgs(propertyName));
}
else
{
if (wait)
{
dispatcher.Invoke(eventRaiser, new PropertyChangedEventArgs(propertyName));
}
else
{
dispatcher.BeginInvoke(eventRaiser, new PropertyChangedEventArgs(propertyName));
}
}
}
public static void SyncNotify(this INotifyPropertyChanged host, string propertyName, Action<string> eventRaiser, bool wait = false, Dispatcher dispatcher = null)
{
Contract.Requires<ArgumentNullException>(host != null);
Contract.Requires<ArgumentException>(string.IsNullOrWhiteSpace(propertyName));
Contract.Requires<ArgumentNullException>(eventRaiser != null);
dispatcher = dispatcher ?? System.Windows.Threading.Dispatcher.CurrentDispatcher;
if (dispatcher.Thread == Thread.CurrentThread)
{
eventRaiser(propertyName);
}
else
{
if (wait)
{
dispatcher.Invoke(eventRaiser, propertyName);
}
else
{
dispatcher.BeginInvoke(eventRaiser, propertyName);
}
}
}
public static void SyncNotify(this INotifyPropertyChanged host, string propertyName, Action<object, PropertyChangedEventArgs> eventRaiser, bool wait = false, Dispatcher dispatcher = null)
{
Contract.Requires<ArgumentNullException>(host != null);
Contract.Requires<ArgumentException>(string.IsNullOrWhiteSpace(propertyName));
Contract.Requires<ArgumentNullException>(eventRaiser != null);
dispatcher = dispatcher ?? System.Windows.Threading.Dispatcher.CurrentDispatcher;
if (dispatcher.Thread == Thread.CurrentThread)
{
eventRaiser(host, new PropertyChangedEventArgs(propertyName));
}
else
{
if (wait)
{
dispatcher.Invoke(eventRaiser, host, new PropertyChangedEventArgs(propertyName));
}
else
{
dispatcher.BeginInvoke(eventRaiser, host, new PropertyChangedEventArgs(propertyName));
}
}
}
public static void SyncNotify(this INotifyPropertyChanged host, string propertyName, Action<object, string> eventRaiser, bool wait = false, Dispatcher dispatcher = null)
{
Contract.Requires<ArgumentNullException>(host != null);
Contract.Requires<ArgumentException>(string.IsNullOrWhiteSpace(propertyName));
Contract.Requires<ArgumentNullException>(eventRaiser != null);
dispatcher = dispatcher ?? System.Windows.Threading.Dispatcher.CurrentDispatcher;
if (dispatcher.Thread == Thread.CurrentThread)
{
eventRaiser(host, propertyName);
}
else
{
if (wait)
{
dispatcher.Invoke(eventRaiser, host, propertyName);
}
else
{
dispatcher.BeginInvoke(eventRaiser, host, propertyName);
}
}
}
}

These extension methods can be called inside the view model, and it ensures that the event is raised on the dispatcher thread.
Since these extension methods uses delegate to invoke the event raiser, so it is unnecessary to worry about the accessibility of the event raiser, event it is declared as protected or private. And 4 overloads can handle most common event raisers.