Well you have three basic options if you want to keep the code separate from your main EXE project.
1. Put your validation or forms (or whatever!) in a DLL.
2. Use a "schema" or some custom XML-type file for validation.
3. Use compile-on-demand.
1. You could create a DLL with a class specific to a form that handles all the validation and exposes a method or two (whatever you need) such as "ValidateForm()". It could even host a form that displays custom errors. A DLL is the fastest, execution-wise, but means separating out your logic "far" from the form.
2. In my current projects, we store our validation in XML format (based on a modified version of a "standard" for validation - can't remember the name right now but it's weird). The concept is to code an "assert" that evaluates to true or false. You reference data in the dataset (whatever rows/columns you need) and it returns a true or false. It works well because we can put the validation right in the same XSD file that stores the data. An XSD is an XML file that represents a DataSet. A typical "assert" might look like (it's XPath, a query language for XML):
test="/*/Customer[not(FirstName) and MiddleName]"
That means, return rows in Customer that have no FirstName (it's null in the table) and have a MiddleName. If that returns a row (asserts as true) then there's an error - meaning the user needs to get a message that this isn't allowed. It's messy (XPath can be quite lengthy at times), but it's very dynamic and it keeps the rules with the data.
3. To compile on demand, you basically have C# or VB.NET code in a file and load it, compile it, and run it at runtime. You can actually invoke the .NET compiler from within code. I've not done it but there are numerous threads on this forum, many by divil, that explain how to do it. It's very flexible, but means you need to store that extra raw code somewhere on a client machine or download it at runtime and compile it. It's more robust than a DLL but also harder to implement and test. Also, it will take a tad longer since it must be compiled (again, I haven't tried this but I assume this time is pretty insignificant assuming a small piece of code).
There are probably many other options, those are just the ones I've tried or heard of.
-Ner