How to: Conditional use of UnityEditor In DLL?

I’m attempting to create a simple utility function DLL, but seem to be running into dependency issues in general and an argument exception specifically, when I try to “build&run” the project that uses this DLL.

The issue arises because I want certain code from the DLL executed when in the editor, and other code, when not in the editor (built project). E.g. using DestoryImmidiate() when in the editor and not in play-mode, and Destroy() otherwise.

I’ve attempted using the Conditional attribute in the DLL, as well as pre-processor pragmas('#if UNITY_EDITOR`). Alas, even with everything else compiling and running ok, the lack of UnityEditor.DLL being allowed in the output “build” prevents it from compiling and generates the following ArgumentException.

ArgumentException: The Assembly UnityEditor is referenced by EditorTools ('Assets/EyeEngines/EditorTools.dll'). But the dll is not allowed to be included or could not be found.

Is it possible to put conditional UnityEditor code like this into a DLL? If so, how?

One obvious workaround is to create TWO versions of the DLL (one with the UNITY_EDITOR pragma defined, one with it undefined), but unless Unity has some way to automatically use the right one, I don’t like it: too confusing for users of the dll (Initial tests of this method generated “class redefined” compilation errors in editor.)

New and improved answer:

I finally figured out a better solution for this….

only TWO assemblies (DLL’s) are created, one to run in the player, one to run in the editor.

In the assembly that will run in the player, we define inside our class, a (few) public static delegate.

using UniyEngine;

 /// <summary>
/// This class allows player dlls to compile in the player (where UnityEditor.dll may not be referenced) while accessing certain Editor-only Functions. 
/// When NOT being run in the editor these functions will immidiately return with a default value.  
/// But if running in the Editor, they will invoke the approate Editor-only function.
/// </summary>
static public class EditorAdapterFunctions
{

    public delegate void DoSomethingReturnNothingDelegate();
    public delegate string GetStringUsingObjectDelegate(Object o);

    static public DoSomethingReturnNothingDelegate EditorRepaintAllViews = null;
    static void RepaintAllViews()
    {
        if (EditorRepaintAllViews != null)
            EditorRepaintAllViews();
    }

    
    static public GetStringUsingObjectDelegate GetAssetPathEditor = null;
    static string GetAssetPath(Object obj)
    {
        if (GetAssetPathEditor != null)
            return GetAssetPathEditor(obj);
        return "";
    }

    static public DoSomethingReturnNothingDelegate RefreshHierarchyEditor = null;
    
    static public void RefreshHierarchy()
    {
        if (RefreshHierarchyEditor != null)
            RefreshHierarchyEditor();
    }
    
}

These funtions will obviously invoke NOTHING, unless we do something else.

So next we define an EDITOR based class, that will be included in the Editor (only) dll.

using UnityEditor;
    public class EditorAdapterFunctionsEditorComponent
{
    [InitializeOnLoadMethod]
    static private void Init()
    {
        EditorAdapterFunctions.EditorRepaintAllViews = UnityEditorInternal.InternalEditorUtility.RepaintAllViews;
        EditorAdapterFunctions.GetAssetPathEditor = AssetDatabase.GetAssetPath;
        EditorAdapterFunctions.RefreshHierarchyEditor = RefreshHierarchy;
    }
    static public void RefreshHierarchy()
    {
        EditorApplication.DirtyHierarchyWindowSorting();
        EditorApplication.RepaintHierarchyWindow();
    }
}

Now, when the Editor is loaded, this class simply assigns the Editor only functions to the delegates in our Non-editor class.

RESULT:

When the Editor DLL’s are NOT in use (like when building the final project), the delegate remains null, and the function is not invoked.

When the Editor DLL’s ARE in use, the editor function gets invoked via the assigned delegate.

OLD ANSWER:
Here is one non-ideal workaround I came up with.

Define the class(es) TWICE; once for the editor dll, and once for the non-editor dll. (So, both DLL project’s will have a reference to the same file)

I mentioned this in the OP. But, to avoid compilation errors, we define each version of the class in different namespaces, using the compile-time pragma.

(DLL code)

#if UNITY_EDITOR
 namespace UnityExtensionsEditor  //the editor version DLL will compile this
#else
  namespace UnityExtensions //the non-editor version DLL will compile this
#endif
class GameObjectExtensions....

Now, in the using-project, the user can simply specify:

(using-project code)

#if UNITY_EDITOR
 using UnityEditor;
 using UnityExtensionsEditor  //the editor version of the project will compile this
#else
 using UnityExtensions //the non-editor version of the project will compile this
#endif

This way, the appropriate GameObjectExtensions class (either UnityExtensionsEditor.GameObjectExtensions or UnityExtensions.GameObjectExtensions ) will be used in the compiled (using-project) code.

I feel like the fact that I’m defining the same class name(s) in two different namespaces, is going to cause problems. Is it acceptable in this case?

Note: Using the (DLL code) above directly in a unity project will lead to errors unless a copy (yuk) of the file is put in the unity project’s editor folder.
Also worth noting is that BOTH DLL’s will need to go in a non-editor folder of the using-project.

#if UNITY_STANDALONE
//do stuff
#endif

#if UNITY_EDITOR
//do other stuff
#endif