I want to rename all the classes and variables in my code to make it more obfuscated. For example, this sample code:
public class Dog
{
public Dog()
{
Bark(4);
}
private void Bark(int times)
{
//Do something
}
}
becomes:
public class Cat
{
public Cat()
{
Wood(4);
}
private void Wood(int asdasd)
{
//Do something
}
}
If this is not possible, perhaps something even simpler where we simply add a character to the middle of every variable/name:
public class Do1g
{
public Do1g()
{
Bar1k(4);
}
private void Bar1k(int time1s)
{
//Do something
}
}
The functionality stays the same, and it is human-readable; however, all information on variable namings, classes, methods, etc, are changed.
Is there a way to obfuscate, while maintaining readability?
You can use Visual Studio Code Model to rename symbols. For example, to add 'x' to the current function name:
EnvDTE.TextSelection ts = DTE.ActiveWindow.Selection as EnvDTE.TextSelection;
EnvDTE80.CodeElement2 func = ts.ActivePoint.CodeElement[vsCMElement.vsCMElementFunction]
as EnvDTE80.CodeElement2;
func.RenameSymbol(func.Name + "x");
(You can run this code with Visual Commander or use in your own extension).
This rename operation also updates all references. You can naturally expand this sample to rename classes, namespaces and process files, projects.
Firstly I have no idea how this could ever be used but, in the comments you said that creating a new object that looks like the desired object is acceptable so
Here is my proposal
Read all the methods of the class using reflection
Create a List with all the properties's and methods's names from step 1
From there you can create a new object using LINQ with the names created from the list you created.
Keep in mind I don't know how or even if this would work.
Related
I want to create an alias for a class name. The following syntax would be perfect:
public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
...
}
public class MyName = LongClassNameOrOneThatContainsVersionOrDomainSpecificName;
but it won't compile.
Example
Note This example is provided for convenience only. Don't try to solve this particular problem by suggesting changing the design of the entire system. The presence, or lack, of this example doesn't change the original question.
Some existing code depends on the presence of a static class:
public static class ColorScheme
{
...
}
This color scheme is the Outlook 2003 color scheme. i want to introduce an Outlook 2007 color scheme, while retaining the Outlook 2003 color scheme:
public static class Outlook2003ColorScheme
{
...
}
public static class Outlook2007ColorScheme
{
...
}
But i'm still faced with the fact that the code depends on the presence of a static class called ColorScheme. My first thought was to create a ColorScheme class that I will inherit from either Outlook2003 or Outlook2007:
public static class ColorScheme : Outlook2007ColorScheme
{
}
but you cannot inherit from a static class.
My next thought was to create the static ColorScheme class, but make Outlook2003ColorScheme and Outlook2007ColorScheme classes non-static. Then a static variable in the static ColorScheme class can point to either "true" color scheme:
public static class ColorScheme
{
private static CustomColorScheme = new Outlook2007ColorScheme();
...
}
private class CustomColorScheme
{
...
}
private class Outlook2008ColorScheme : CustomColorScheme
{
...
}
private class Outlook2003ColorScheme : CustomColorScheme
{
...
}
but that would require me to convert a class composed entirly of readonly static Colors into overridable properties, and then my ColorScheme class would need to have the 30 different property getters thunk down into the contained object.
That's just too much typing.
So my next thought was to alias the class:
public static ColorScheme = Outlook2007ColorScheme;
But that doesn't compile.
How can I alias a static class into another name?
Update: Can someone please add the answer "You cannot do this in C#", so I can mark that as the accepted answer. Anyone else wanting the answer to the same question will find this question, the accepted answer, and a number of workarounds that might, or might not, be useful.
I just want to close this question out.
You can’t. The next best thing you can do is have using declarations in the files that use the class.
For example, you could rewrite the dependent code using an import alias (as a quasi-typedef substitute):
using ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;
Unfortunately this needs to go into every scope/file that uses the name.
I therefore don't know if this is practical in your case.
You can make an alias for your class by adding this line of code:
using Outlook2007ColorScheme = YourNameSpace.ColorScheme;
You cannot alias a class name in C#.
There are things you can do that are not aliasing a class name in C#.
But to answer the original question: you cannot alias a class name in C#.
Update: People are confused why using doesn't work. Example:
Form1.cs
private void button1_Click(object sender, EventArgs e)
{
this.BackColor = ColorScheme.ApplyColorScheme(this.BackColor);
}
ColorScheme.cs
class ColorScheme
{
public static Color ApplyColorScheme(Color c) { ... }
}
And everything works. Now i want to create a new class, and alias ColorScheme to it (so that no code needs to be modified):
ColorScheme.cs
using ColorScheme = Outlook2007ColorScheme;
class Outlook2007ColorScheme
{
public static Color ApplyColorScheme(Color c) { ... }
}
Ohh, i'm sorry. This code doesn't compile:
My question was how to alias a class in C#. It cannot be done. There are things i can do that are not aliasing a class name in C#:
change everyone who depends on ColorScheme to using ColorScheme instead (code change workaround because i cannot alias)
change everyone who depends on ColorScheme to use a factory pattern them a polymorphic class or interface (code change workaround because i cannot alias)
But these workarounds involve breaking existing code: not an option.
If people depend on the presence of a ColorScheme class, i have to actually copy/paste a ColorScheme class.
In other words: i cannot alias a class name in C#.
This contrasts with other object oriented languages, where i could define the alias:
ColorScheme = Outlook2007ColorScheme
and i'd be done.
You want a (Factory|Singleton), depending on your requirements. The premise is to make it so that the client code doesn't have to know which color scheme it is getting. If the color scheme should be application wide, a singleton should be fine. If you may use a different scheme in different circumstances, a Factory pattern is probably the way to go. Either way, when the color scheme needs to change, the code only has to be changed in one place.
public interface ColorScheme {
Color TitleBar { get; }
Color Background{ get; }
...
}
public static class ColorSchemeFactory {
private static ColorScheme scheme = new Outlook2007ColorScheme();
public static ColorScheme GetColorScheme() { //Add applicable arguments
return scheme;
}
}
public class Outlook2003ColorScheme: ColorScheme {
public Color TitleBar {
get { return Color.LightBlue; }
}
public Color Background {
get { return Color.Gray; }
}
}
public class Outlook2007ColorScheme: ColorScheme {
public Color TitleBar {
get { return Color.Blue; }
}
public Color Background {
get { return Color.White; }
}
}
try this:
using ColorScheme=[fully qualified].Outlook2007ColorScheme
I'm adding this comment for users finding this long after OP accepted their "answer".
Aliasing in C# works by specifying the class name using it's fully qualified namespace. One defined, the alias name can be used within it's scope.
Example.
using aliasClass = Fully.Qualified.Namespace.Example;
//Example being the class in the Fully.Qualified.Namespace
public class Test{
public void Test_Function(){
aliasClass.DoStuff();
//aliasClass here representing the Example class thus aliasing
//aliasClass will be in scope for all code in my Test.cs file
}
}
Apologies for the quickly typed code but hopefully it explains how this should be implemented so that users aren't mislead into believing it cannot be done in C#.
Aliasing the way that you would like to do it will not work in C#. This is because aliasing is done through the using directive, which is limited to the file/namespace in question. If you have 50 files that use the old class name, that will mean 50 places to update.
That said, I think there is an easy solution to make your code change as minimal as possible. Make the ColorScheme class a facade for your calls to the actual classes with the implementation, and use the using in that file to determine which ColorScheme you use.
In other words, do this:
using CurrentColorScheme = Outlook2007ColorScheme;
public static class ColorScheme
{
public static Color ApplyColorScheme(Color c)
{
return CurrentColorScheme.ApplyColorScheme(c);
}
public static Something DoSomethingElse(Param a, Param b)
{
return CurrentColorScheme.DoSomethingElse(a, b);
}
}
Then in your code behind, change nothing:
private void button1_Click(object sender, EventArgs e)
{
this.BackColor = ColorScheme.ApplyColorScheme(this.BackColor);
}
You can then update the values of ColorScheme by updating one line of code (using CurrentColorScheme = Outlook2008ColorScheme;).
A couple concerns here:
Every new method or property definition will then need to be added in two places, to the ColorScheme class and to the Outlook2007ColorScheme class. This is extra work, but if this is true legacy code, it shouldn't be a frequent occurence. As a bonus, the code in ColorScheme is so simple that any possible bug is very obvious.
This use of static classes doesn't seem natural to me; I probably would try to refactor the legacy code to do this differently, but I understand too that your situation may not allow that.
If you already have a ColorScheme class that you're replacing, this approach and any other could be a problem. I would advise that you rename that class to something like ColorSchemeOld, and then access it through using CurrentColorScheme = ColorSchemeOld;.
I suppose you can always inherit from the base class with nothing added
public class Child : MyReallyReallyLongNamedClass {}
UPDATE
But if you have the capability of refactoring the class itself: A class name is usually unnecessarily long due to lack of namespaces.
If you see cases as ApiLoginUser, DataBaseUser, WebPortalLoginUser, is usually indication of lack of namespace due the fear that the name User might conflict.
In this case however, you can use namespace alias ,as it has been pointed out in above posts
using LoginApi = MyCompany.Api.Login;
using AuthDB = MyCompany.DataBase.Auth;
using ViewModels = MyCompany.BananasPortal.Models;
// ...
AuthDB.User dbUser;
using ( var ctxt = new AuthDB.AuthContext() )
{
dbUser = ctxt.Users.Find(userId);
}
var apiUser = new LoginApi.Models.User {
Username = dbUser.EmailAddess,
Password = "*****"
};
LoginApi.UserSession apiUserSession = await LoginApi.Login(apiUser);
var vm = new ViewModels.User(apiUserSession.User.Details);
return View(vm);
Note how the class names are all User, but in different namespaces. Quoting PEP-20: Zen of Python:
Namespaces are one honking great idea -- let's do more of those!
Hope this helps
Is it possible to change to using an interface?
Perhaps you could create an IColorScheme interface that all of the classes implement?
This would work well with the factory pattern as shown by Chris Marasti-Georg
It's a very late partial answer - but if you define the same class 'ColorScheme', in the same namespace 'Outlook', but in separate assemblies, one called Outlook2003 and the other Outlook2007, then all you need to do is reference the appropriate assembly.
The best way I've found to simulate alias in C# is inheritance.
Create a new class that inherits from the original class:
public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
...
}
public class MyName
: LongClassNameOrOneThatContainsVersionOrDomainSpecificName
{
}
The only thing that you would need to be careful is the constructor. You need to provide a a constructor for MyName class.
public class MyName
: LongClassNameOrOneThatContainsVersionOrDomainSpecificName
{
public MyName(T1 param1, T2 param2) : base(param1, param2) {}
}
In this example I'm using T1 and T2 as generic types, since I don't know the constructor for your LongClassNameOrOneThatContainsVersionOrDomainSpecificName class.
Beware, though, that this is not alias. Doing this to you application might run into some issues or problems. You might need to create some extra code to check for types, or even overload some operators.
I just started testing Marten (2.9), and so far I am loving it. However, I am not sure I am following the DocumentStore.For method. For example, in my "dbhandler" for Marten, I can write:
public MartenDbHandler()
{
store = DocumentStore.For(_ =>
{
_.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
_.Connection("host=localhost;database=marten;password=root;username=postgres");
_.Schema.For<Customer>().Index(x => x.PopulationRegistryNumber);
});
}
but naturally, I do not want to have all that schema code when I initialize the database and supply the connection string.
So I thought, maybe I can pass on the store variable, and do the same, but then the For thing doesn't exist:
... and I haven't really found a way to set the Schema in any other way.
What I really want to do is to have an Interface, that is dynamically loaded and executed (via Reflection) when I start my application, that handles those things, like an IMartenMetaData that looks something like:
public interface IMartenMetaData
{
SetMetaData(DocumentStore store);
}
and then implement the schema things in that/those classes, but that doesn't work because I can't use the DocumentStore to set the meta.
Keep it simple. The document store is supposed to have a single instance in your app and you define the schema properties during construction. No need to abstract the store.
One way is you can create your own implementation of DocumentStore. You can refer to the test document store classes in the source code.
Update:
You can find the sample here https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/TestingDocumentStore.cs
I managed to do a much nice approach to keep it more dynamic and not all in the construction of DocumentStore.
Please see code below. The idea is straightforward:
Create the StoreOptions separately
Before creation of the DocumentStore, run method that via Reflection finds all classes of a certain Type that will add table meta data
Create the DocumentStore
public MartenDbHandler()
{
StoreOptions so = new StoreOptions();
so.Connection("host=localhost;database=marten;password=root;username=postgres");
so.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
SetTableMeta(so);
store = new DocumentStore(so);
}
private void SetTableMeta(StoreOptions storeOptions)
{
// We get the current assembly through the current class
var currentAssembly = Assembly.GetExecutingAssembly();
// we filter the defined classes according to the interfaces they implement
var stuff = currentAssembly.DefinedTypes.Where(type => type.IsSubclassOf(typeof(MartenTableMetaDataBase))).ToList();
foreach (Type type in stuff)
{
IMartenTableMetaData temp = (IMartenTableMetaData)Activator.CreateInstance(type);
temp.SetTableMetaData(storeOptions);
}
OnLogEvent?.Invoke(this, $"{stuff.Count} table meta data initialized");
}
The IMartenTableMetaData is a base class for the IMartenTableMetaData interface. In the example below, the base class isn't used, but I normally find it good to have a base class (I use a similar approach to another ORM, where I actually use the base class). But, the base class can of course be removed if you have no use for it.
internal abstract class MartenTableMetaDataBase : IMartenTableMetaData
{
public void SetTableMetaData(StoreOptions storeOptions)
{
SetSpecificTableMetaData(storeOptions);
}
protected abstract void SetSpecificTableMetaData(StoreOptions storeOptions);
}
and the interface:
public interface IMartenTableMetaData
{
void SetTableMetaData(StoreOptions storeOptions);
}
So, I can now create a class for each Type I want to add meta data too, like this:
internal class MartenTableMetaDataCustomer : MartenTableMetaDataBase
{
protected override void SetSpecificTableMetaData(StoreOptions storeOptions)
{
storeOptions.Schema.For<Customer>().Index(x => x.Muni);
}
}
or
internal class MartenTableMetaDataDriver : MartenTableMetaDataBase
{
protected override void SetSpecificTableMetaData(StoreOptions storeOptions)
{
storeOptions.Schema.For<Driver>().Index(x => x.Username);
}
}
etc.
This will keep the Marten DB handler clean and meta data separated into specific classes for readability, clarity and all that stuff =)
Edit 1:If anyone has a better Title for that, feel free to tell me or edit it yourself.
Edit 2: Thanks for your contribution guys, the answer given is almost what I need with some tweaks and I'm thankful for the small stuff here. Really learnt much today!
Little stuff here that I'm banging my head on for a while now.
I want to create a Slideshow and want the logic in the Image objects itself.
The programm should be able to set a desired transition or just a random one so
I wanted to create a Transition Superclass with the general stuff and spezialize
it in the subclasses. So I have Transitions.cs (with no Code currently inside it)
and no derived class. I want it to be in the way of adding a single .cs file
extending Transitions.cs and not change any other code to implement a new Transition.
The Code I currently have looks something like this but I guess my
description is more helpful than the code
public class SlideImages : MonoBehaviour {
Image image;
Image nextImage;
int tracker;
private void Transition(int ID)
{
/*Something to choose a transition based on the ID
*Transitions.cs is the superclass of all different transitions
*f.e. Ken-Burns Effect, or scattered Transition which all extend from it
*/
}
~SlideImages()
{
//TODO: Pop and Push
}
}
I had the idea of something along the lines of static stuff to workaround that
looks like this but it doesn't work I suppose
public class Transitions : MonoBehaviour {
public static int TransitionID;
protected static int SubclassCount;
protected static void SetID()
{
TransitionID = Transitions.SubclassCount;
Transitions.SubclassCount++;
}
}
I did look into the state design pattern but I don't want to implement it as I just need the state to be chosen once and shortlived. The Image Objects themself only have a lifetime of around a few seconds. I don't want to do the usual if-nesting or just put all the code inside the SlideImages.cs. Is there any good guidance to it or stuff that goes very indepth into inheritance and such stuff?
Appreciate all the input.
There are two straight-forward solutions to what you want to do. Your basic problem is that you want to be able to dynamically add functionality to your program but you don't want to have knowledge of what has been added in order to use it. The most hack-ish way of doing it is to use Actions instead of subclassing. When you want to add another transition you just update an actions list like this:
public static class Transitions
{
private static Action[] TransitionStrategies = new Action[]
{
() => { /* One way of performing a transition */ },
() => { /* Another way of performing a transition */ },
() => { /* Keep adding methods and calling them here for each transition type */ }
}
public static void PerformTransition(int? transitionIndex = null)
{
int effectiveIndex;
// if the transition index is null, use a random one
if (transitionIndex == null)
{
effectiveIndex = new Random().Next(0, TransitionStrategies.Length);
}
else
{
effectiveIndex = transitionIndex.Value;
}
// perform the transition
TransitionStrategies[effectiveIndex]();
}
}
The above approach is simple but all of the logic (or at least references to the logic depending on where you implement the actual work for the transitions) is in one place. It also has the potential to get quite messy depending on how many transitions you are adding and how many developers are touching this codebase. It also requires all functionality to be added by someone with access to the full codebase and requires a recompilation each time new transitions are added.
A more complex but much more maintainable and flexible approach in the long term is to use modules (or plugins for our purposes). Each transition in that approach is provided by either a shared module or a specific module and is a subclass of a base AbstractTransition class or an implementation of an ITransition interface depending on how you want to go about doing that. Use post-build tasks to place all of your module dlls in a single directory accessible to your main program (anyone else given permission can put transition module dlls there too). When your program launches, it dynamically loads all dlls from that directory (no recompilation required when new transitions are added as long as the right dlls are in that directory) and pulls out all of the classes implementing that interface. Each of those interface implementations are instantiated and placed into a data structure after which you can use a similar strategy to the above's PerformTransition method to perform a random one or one based on an ID instead of an index. I can edit this question with an example of that structure if you would like.
Edit: You didn't ask for it yet, but here's an example with plugins/modules.
First, create a project to load and run the transitions. This example will use a project called ModuleDemo. Give it a main method like this:
static void Main(string[] args)
{
// create a list to hold the transitions we load
List<AbstractTransition> transitions = new List<AbstractTransition>();
// load each module we find in the modules directory
foreach (string dllFilepath in Directory.EnumerateFiles("Modules", "*.dll"))
// this should really read from the app config to get the module directory
{
Assembly dllAssembly = Assembly.LoadFrom(dllFilepath);
transitions.AddRange(dllAssembly.GetTypes()
.Where(type => typeof(AbstractTransition).IsAssignableFrom(type))
.Select(type => (AbstractTransition) Activator.CreateInstance(type)));
}
// show what's been loaded
foreach (AbstractTransition transition in transitions)
{
Console.WriteLine("Loaded transition with id {0}", transition.TransitionId);
// execute just to show how it's done
transition.PerformTransition();
}
Console.Read(); // pause
}
You'll notice that the method references an AbstractTransition class. Let's create a separate TransitionModule project for that now. This is the project that the modules will reference:
namespace TransitionModule
{
public abstract class AbstractTransition
{
public readonly int TransitionId;
public abstract void PerformTransition();
protected AbstractTransition(int transitionId)
{
TransitionId = transitionId;
}
// you can add functionality here as you see fit
}
}
Now that we have an abstract transition class for the plugins to implement and a functioning plugin loader, we can go ahead and create a few transition plugins.
I created a Modules folder for this in my solution but it doesn't really matter.
First module in a FlipTransition project:
using System;
using TransitionModule;
namespace FlipTransition
{
public class FlipTransition : AbstractTransition
{
public FlipTransition() : base(2)
{
}
public override void PerformTransition()
{
Console.WriteLine("Performing flip transition");
}
}
}
Second module in a SlideTransition project:
using System;
using TransitionModule;
namespace SlideTransition
{
public class SlideTransition : AbstractTransition
{
public SlideTransition() : base(1)
{
}
public override void PerformTransition()
{
Console.WriteLine("Performing slide transition");
}
}
}
Note that each of those projects needs to reference the TransitionModule project but the main project doesn't need to know about any of the other projects.
Now we have 2 transition plugins and a plugin loader. Since the plugin loader is going to load the modules from a Modules directory, go to the /bin/Debug directory of the main project and make a Modules directory. Copy all of the dlls from the /bin/Debug directories of the transition plugin projects into that directory as well. All of this can be automated with post-build tasks later on.
Go ahead and run the program. You should get output like this:
Loaded transition with id 2
Performing flip transition
Loaded transition with id 1
Performing slide transition
There's a lot you can do to make this more elegant, but this is at least a simple example of how you can use a plugin-based architecture to provide what you need.
You could try playing around with abstract classes, create a base abstract class for image transitioning;
public abstract class ImageTransition
{
protected int imageId { get; set; }
public Dictionary<int, Image> ImageDictionary { get; set; }
protected abstract void TransitionToNextImageId();
public Image GetNextImage()
{
TransitionToNextImageId();
return ImageDictionary[imageId];
}
}
You then create new Transition types that inherit from this base class and have their own implementation of the TransitionToNextImageId method;
public class InTurnImageTransition : ImageTransition
{
protected override void TransitionToNextImageId()
{
if(this.imageId < ImageDictionary.Count)
this.imageId ++;
}
}
public class RandomImageTransition : ImageTransition
{
protected override void TransitionToNextImageId()
{
imageId = new Random().Next(0, ImageDictionary.Count);
}
}
This allows you to build up some custom transitions however you wish.
-Edit-
You would of course fill the dictionary ImageDictionary before calling the GetNextImage method.
I'm trying to create a mechanism that will allow the application to decide (in runtime) whether to execute some functionality.
"Some Functionality" can be anything, it can be c# code which is contained in several classes in several dlls, it can be UI, it can be database query execution, etc.
Most importantly, it should fit in the current existing infrastructure I have, which I cannot re-design and build from scratch.
The more I think of it, it seems like the only solution I can use would be to hold some table which will be the "functionality repository" and it will tell (by unique key) if a functionality is on / off.
Then in code, I will have to place in each spot which handles such functionality an if else statement.
E.g.
If(functionalityEnabled)?
DoFunctionality()
Else
DoTheUsusal()
Is there a better way or a better design to implement it? I would like to keep the solution as simple as possible, but on the other hand, this solution is really ugly and will eventually make my code looks like spaghetti code.
Your thoughts will be appreciated,
I'm using c# with sql server, web api for web services.
Edit:
I want to say that I appreciate the time and effort of everyone answering my question, there were some really interesting ideas that you brought up.
I eventually marked #dasblinkenlight answer since it suited by need the best, though other answers here are really good and may be useful to others.
Thank you.
If you have two classes that implement the same interface, your application can call the functionality (methods, properties) of the class without knowing exactly if it is calling the basic functionality or the alternative functionality:
IFunctionalityX {
DoIt();
}
class BasicFunctionalityX: IFunctionalityX {
public DoIt() {
// Default behaviour goes here
}
}
class PluginFunctionalityX: IFunctionalityX {
public DoIt() {
// Alternative functionality.
}
}
If PluginFunctionalityX shares parts of its implementation with BasicFunctionalityX, you may inherit it from the other, but whether you do or not doesn't really matter. As long as you use the interface, that is what counts, and you can use this method regardless of whether the classes are related or not.
In the initialization of your program, you can make the decision once and create an instance of the right class. You may store this class in some container that holds all your functionalities. FunctionalityX is a property of interface IFunctionalityX, and you can make other interfaces (and properties) for other functionalities.
if (functionalityXEnabled) {
FunctionalityContainer.FunctionalityX = new PluginFunctionality();
} else {
FunctionalityContainer.FunctionalityX = new BasicFunctionality();
}
Then, in the rest of your application, you can call your functionality through:
FunctionalityContainer.FunctionalityX.DoIt();
Instead of implementing this from scratch you may use a dependancy injection library, like Unity. This also allows you to more easily get an instance of the right functionality at the time you need it without having to create them all at the start of your program, and without writing elaborate constructor code for all fucntionalities.
You want to dispatch your code differently at runtime dependent on a configuration setting. Conditionals and polymorphism are two ways of doing so.
Conditionals
At runtime, check for values using if, switch or other lookup methods. You're already doing these.
if (configFile.cloudAccount == null) {
saveFileToDisk();
} else saveFileToCloud();
Advantages
They're conditionals, you really can't avoid having to do one at some point in any nontrivial development project
Disadvantages
Doing them at every point in your application would be painful, though. So they're best combined with other strategies to minimise their use
Polymorphism
When loading your application, read through the configuration file and construct your application's components accordingly:
interface IFileSaver { /* Used to save files in your application */ }
class DiskSaver : IFileSaver { /* The default file saving class */ }
class CloudSaver : IFileSaver { /* If they've configured a cloud account */ }
// EXAMPLE USE
int Main (...) {
// Setup your application, load a config file.
// You'll need to check the config with a conditional
// here (uh oh) but other components of your application
// will just use the IFileSaver interface
if (configFile.cloudAccount != null) {
YourApplication.FileSaver = new CloudSaver(configFile.cloudAccount);
} else {
YourApplication.FileSaver = new DiskSaver();
}
}
// Somewhere else in your application
void SaveCurrentDocument() {
// No if's needed, it was front loaded when initialising
// the application
YourApplication.FileSaver.Save();
}
Advantages
Fits in nicely with object-oriented design
All your configuration checks are front loaded. After loading in the correct classes the rest of your program will use them, oblivious to their actual implementation. Because of that, you don't need to do if checks throughout your code.
Compiler will be able to statically check type errors in your approach
Disadvantages
Only as flexible as your class's interface. Maybe you want some extra steps and checks to occur with a CloudSaver, they'd better fit into the pre-existing interface; otherwise, they won't happen.
Long story short - conditionals let you explicitly perform the checks whenever they're needed so, in principle, you get a lot of procedural flexibility. For example, maybe the SaveAs routine needs to save files slightly differently than the Save routine. However, as you've identified, this leads to long repetitive code. In those cases, structuring your code to use polymorphism might help out.
Either way, you will almost certainly need to have some amount of conditional checks wherever there is flexibility in your application.
Note: There are many other ways of achieving runtime config checks, I'm just pointing out the most common (and usually straightforward)
A once-popular quip among OO programmers has been that every conditional in the code indicate a missed opportunity to subclass. Although this rule is far from being universal, and it falls short when it comes to composition, there is a grain of truth to it, especially when you see the same condition popping up in multiple ifs across different methods of the same class.
A common way of dealing with ifs like that is using some combination of inheritance and composition, and moving the decision to a single place where your object is being created.
The inheritance way looks like this:
interface Doer {
void doSomething();
}
class BasicDoer implements Doer {
public void doSomething() {
...
}
}
class EnhancedDoer extends BasicDoer {
public void doSomething() {
base.doSomething();
...
}
}
// At construction time:
Doer doer;
if (someCondition)
doer = new BasicDoer();
else
doer = new EnhancedDoer();
The composition way looks like this:
interface Doer {
void doSomething();
}
// Create several implementations of Activity, then...
// At construction time:
List<Doer> doers = new ArrayList<>();
if (someCondition1)
doers.add(new SomeKindOfDoer());
if (someCondition2)
doers.add(new AnotherKindOfDoer());
if (someCondition3)
doers.add(new YetAnotherKindOfDoer());
Now instead of an if you do this:
for (Doer d : doers) {
d.doSomething();
}
If it's just a single condition then you have no choice but to use if else and is perfect for single conditions.
If you have more then 1 condition, you may think of using Switch statement.
As far as you are worried about your code going to look complicated with if else statement, put your code within functions,
if(condition)
{
DoThis();
}
else
{
DoSomethingElse();
}
Maybe something similar to strategy design pattern (incapsulation of behaviour) will make it more managable if functionality doesn't require lots of interaction with object data (though interaction is possible). Pros: readable extendable code, cons: lots of code.
namespace SomethingLikeStrategy
{
public interface Behaviour {
void doThis();
void changeM(ref int m);
void doThat();
}
public class BehaviourOriginal : Behaviour {
public void doThis() {
Console.WriteLine("foo");
}
public void changeM(ref int m) {
m = 20;
}
public void doThat() {
throw new Exception("not implemented");
}
}
public class BehaviourSpecial : Behaviour {
public void doThis() {
Console.WriteLine("bar");
}
public void changeM(ref int m) {
m = 10;
}
public void doThat() {
throw new Exception("not implemented");
}
}
public class MyClass {
Behaviour mBehaviour;
int mM = 0;
public MyClass() {
mBehaviour = new BehaviourOriginal();
}
public void setSpecialBehaviour(bool special) {
if (special) {
mBehaviour = new BehaviourSpecial();
} else {
mBehaviour = new BehaviourOriginal();
}
}
public void doThis() {
mBehaviour.doThis();
}
public void doThat() {
mBehaviour.doThat();
}
public void changeM() {
mBehaviour.changeM(ref mM);
}
public void printM() {
Console.WriteLine(mM);
}
}
class Program
{
public static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass.doThis();
myClass.setSpecialBehaviour(true);
myClass.doThis();
myClass.setSpecialBehaviour(false);
myClass.printM();
myClass.changeM();
myClass.printM();
myClass.setSpecialBehaviour(true);
myClass.changeM();
myClass.printM();
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
I am working in a content management system that uses C# and allows for adding separate code in a central class. One issue that has come up is we would like to have a separate code base for QA and the rest of the site, currently we use the folder structure to switch the call from one class to the other
if (AssetPath == "Websites QA")
{
InputHelperQA.Navigation();//Calling Navigation Section From Helper Class
}
else
{
InputHelper.Navigation();
}
But i feel it is a very tedious way of doing this task. Is there a better way of accomplishing this?, obviously just appending InputHelper + "QA" does not work but some thing along those lines where we only have to call the method once instead of having to wrap an if else around the call.
You really shouldn't have separate code for different environments, besides being branches representing your environments.
You really should store your configuration in a config file or database.
You could do worse than:
1) Have an interface (which you may already have, truth be told)
public interface IInputHelper
{
void Navigation();
}
2) Derive your two instances as you already have:
public class InputHelper : IInputHelper { }
public class InputHelperQA : IInputHelper { }
3) Create some kind of a dispatch manager:
public sealed class InputDispatch
{
private Dictionary<string, IInputHelper> dispatch_ = new Dictionary<string, IInputHelper>(StringComparer.OrdinalIgnoreCase);
public InputDispatch()
{
dispatch_["Websites QA"] = new InputDispatchQA();
dispatch_["Default"] = new InputDispatch();
}
public void Dispatch(string type)
{
Debug.Assert(dispatch_.ContainsKey(type));
dispatch_[type].Navigation();
}
}
I would use Dependency Injection. StructureMap (as just one example) will let you specify which concrete type to provide for an interface via a config file.
http://docs.structuremap.net/XmlConfiguration.htm