Normal mapping usually works like this:
You have a normal map which is a texture containing tangent space normal vectors in the red and green components (XY). You have to transform it to world space (XYZ) and replace your vertex normal with this. All your following light calculations should use this new normal vector. That's it.
The trickiest part is the basis transformation from tangent space to world space which you have to do in the pixel shader. Usually games provide tangent and binormal (also called bitangent) vectors in the vertex buffers for the mesh. Or just store the tangent and calculate the bitangent like this:
bitangent = cross(normal, tangent)
For calculating tangent vectors for the vertices, there is an open source library called mikktspace written in C++. You can derive a C# implementation if there is not one already available. An other option is that you can provide a quaternion representing the tangent space. And the final option is that you can calculate the tangent space inside the pixel shader from screen space derivatives, like this.
When you have you normal, tangent and binormal vectors, which are unit vectors, you can assemble the tangent space transform matrix like so:
tangentBasis = float3x3(tangent, binormal, normal)
If you multiply your tangent space normal vectors which came from the normal map texture, you get the world space normal vector.