If you deploy .NET assemblies to your client machines, some kind of decompilation will always be possible using reflector and similar tools.
However, this situation isn’t materially different to what you’d encounter if you wrote the application in native C++. It is always possible to decompile things – if it were impossible, the processor couldn’t understand it either.
You’re never going to defeat the expert cracker – they’ll treat your security as an intellectual puzzle to be solved for the challenge alone.
The question revolves around how hard it is to defeat your licensing practices and the return on investment.
Sit down with a spreadsheet and look through the possible scenarios – the danger is probably less than you think.
Factors like “ease of use” are visible in your software for any user to observe – so you’d think it easy to copy. But, good User experience is rare (and seldom copied well), because most developers (myself included) are nothing like typical users.
I’d suggest you concentrate on making the job of a cracker harder, cause you can never make it impossible, just non-profitable.
One possibility to try: It’s possible to pre-compile assemblies into native code as a part of the installation process. Paint.NET does this for performance reasons. I believe that once you’ve done this, you can discard the original assemblies and use the optimised, native code editions.