The trick is to abstract on a higher level than the API itself. Abstracting textures, vertex buffers, etc. usually isn't the way to go. You're much better off abstracting the rendering of models, your material system, your world geometry rendering, etc.
When you do it at this higher-level, the abstraction actually becomes a lot nicer and intuitive. When possible, writing this abstraction is a good idea, so you can share code not only across projects but also across platforms.
Abstracting vectors/matrices are a little less efficient in managed code since you can't just re-interpret pointers like you can in C++, but its still not hard.
Microsoft DirectX/XNA MVP