I believe this approach would work, you would just need some handling for parameter/element type match up. This seems like a perfect match for an abstract factory pattern or something similar. You might also save some time using the Revit Lookup tools to identify which parameters match to which types.
It's not ideal, but I do not think that there is a universal solution to changing the level of an element. As far as I understand, the reason for this is that different elements are hosted by and associated with levels in different ways. So Revit's engine under the hood is doing different things to make that work, and the options we have exposed to us in the API therefore differ by type. @jeremy_tammik is the expert in that regard, but this is what I understand to be the case.
Regarding handling moving everything on a given level, that can be accomplished with some changes to my example. Where I have hard-code the level name var newLevelName = "L2"; you could easily replace that with a UI allowing users to select the destination level. Similarly, you could add a UI to allow the user to select a source level, and supply that id to this block of code:
var levelHostedElements = selectedElements
.Where(x => x.LevelId == sourceLevel.Id)
.ToList();
Do you also need help with selection and UI components?