Search code examples
c#.net-3.5c#-3.0compiler-directives

Getting rid of precompiler directives in C#


I've been asked to maintain some not-as-legacy-as-I-would-like code, and it is riddled with compiler directives, making it pretty much unreadable and almost as maintainable. Case in point:

#if CONDITION_1
        protected override void BeforeAdd(LogEntity entity)
#else
        protected override void BeforeAdd(AbstractBusinessEntity entity)
#endif
        {
#if CONDITON_1
            entity.DateTimeInsert = DateTime.Now;
#else
            ((LogEntity) entity).DateTimeInsert = DateTime.Now;
#endif
            base.BeforeAdd(entity);
        }

using directives are even prettier:

#if CONDITION_1
using CompanyName.Configuration;
#endif

#if CONDITION_2||CONDITION_1
using CompanyName.Data;
using CompanyName.Data.SqlBuilders;
#else
using CompanyName.Legacy.Database;
using CompanyName.Legacy.Database.SQLBuilders;
using CompanyName.Legacy.Database.SQLBuilders.parameterTypes;
#endif

I thought I'd give the ConditionalAttribute a go but that won't quite work in this situation

Is there any way I can work my way out of this compiler directive nightmare?

The code is compiled against .NET 3.5.

UPDATE:
Oded answered suggesting removing the compiler directives around the BeforeAdd method thus overloading it. Unfortunately that won't work since both methods are supposed to be overriding an AbstractBusiness class which provides two different implementations depending on which assemblies end up being included:

protected virtual void BeforeAdd(TEntity entity) {}

or

protected virtual void BeforeAdd(AbstractBusinessEntity entity) {}

This code gets its dependencies from a set of libraries de company created some time in the past and have been "upgrading" ever since. They now have 4 different versions of that set of libraries with colliding namespaces and differing implementations. All in the name of "backwards compatibility" with applications that use the (very) old versions.


CONCLUSION

I ended up choosing @Oded's answer because it makes the most sense as a general approach (K.I.S.S. and all that). I could not use it in this case though; what you see here is just the tip of the iceberg. I wouldn't want to K.I.S.S. this code if it paid me.


Solution

  • In the first case, it looks like you could simply have several overloads of the method instead of this construct. Overload resolution should take care of things at this point.

    In the second case (using directives) - you can alias some of the directives and include all of them, using the alias where needed. What happens when all namespaces are included? Any name collisions?