# Making operations more dynamic

I am trying to build something that will allow us to configure "custom" validation for each customer. So if a customer wants to see a value contain a specific char, be specific length, or equal something else they just add a pre-created option. I wrote something that seems to be very primitive, but works. I would like it to be more dynamic. For instance, I can pass in actual C# code and it will perform that operation on the value input and being compared.

public class Operation
{
public object value { get; set; }
public OMagic perform { get; set; }
}

public class Magic
{

public bool Validate(object val, Operation operation)
{
switch (operation.perform)
{
case OMagic.Equal:
return (string)val == (string)operation.value;
case OMagic.NotEqual:
return (string)val != (string)operation.value;
case OMagic.LengthGreaterThan:
return (int)val < (int)operation.value;
case OMagic.LengthEqual:
return (int)val == (int)operation.value;
case OMagic.LengthLessThan:
return (int)val > (int)operation.value;
default:
return false;
}
}
}

public enum OMagic
{
Equal,
NotEqual,
LengthGreaterThan,
LengthEqual,
LengthLessThan

}


That is the primitive code, and here are the tests I wrote (using nunit)

[TestFixtureSetUp]
public void SetupTest()
{
//CurrentMessage = getMessage(WebIZ.Test.UnitTest.Properties.Resources.TestResponse1);
Magic = new Magic();
}

private Magic Magic;

[Test]
public void Text_Compare_Works()
{
Assert.IsTrue(Magic.Validate("yes", new Operation() { value = "yes", perform = OMagic.Equal }));
Assert.IsFalse(Magic.Validate("yes", new Operation() { value = "no", perform = OMagic.Equal }));
Assert.IsTrue(Magic.Validate("yes", new Operation() { value = "no", perform = OMagic.NotEqual }));
Assert.IsFalse(Magic.Validate("yes", new Operation() { value = "yes", perform = OMagic.NotEqual }));
}

[Test]
public void Int_Compare_Works()
{
Assert.IsFalse(Magic.Validate(7, new Operation(){value = 7, perform=OMagic.LengthGreaterThan}));
Assert.IsTrue(Magic.Validate(7, new Operation() { value = 8, perform = OMagic.LengthGreaterThan }));
Assert.IsFalse(Magic.Validate(7, new Operation() { value = 7, perform = OMagic.LengthLessThan }));
Assert.IsTrue(Magic.Validate(7, new Operation() { value = 6, perform = OMagic.LengthLessThan }));
Assert.IsFalse(Magic.Validate(7, new Operation() { value = 8, perform = OMagic.LengthEqual }));
Assert.IsTrue(Magic.Validate(7, new Operation() { value = 7, perform = OMagic.LengthEqual }));
}

• First, I think this sounds more appropriate for Programmers. Second, I cannot understand why I would use Magic.Validate("yes", new Operation() { value = "yes", perform = OMagic.Equal }) rather than "yes".Equals("yes"), etc. – Magus Aug 1 '14 at 22:42
• I think you should have a look @ weblogs.asp.net/scottgu/… – Thomas Junk Aug 2 '14 at 16:25
• @ThomasJunk thanks for the article, but I am trying to stay away from writing bulky link queries. I was looking for something that could reduce the amount of code I would need to pass in. I also was thinking of using funcs, just couldn't remember how to use them. – DeadlyChambers Aug 2 '14 at 18:26
• @Magus I don't usually use the equals, but I will start to explore that option. It seems like a cleaner way, but are you saying this question sounds more appropriate for programmers? This is working code (also very ugly), I just wanted someone to review it and give some advice/better solution. – DeadlyChambers Aug 2 '14 at 18:30
• Again, its not about .Equals() it's about your goal. You want to know if something meets some condition. But ultimately, Assert.IsFalse(Magic.Validate(7, new Operation(){value = 7, perform=OMagic.LengthGreaterThan})); is no different from Assert.IsFalse(7 > 7); - in other words, your .Validate() method does nothing. There is no point even writing a more flexible one. For simple comparisons, just compare. – Magus Aug 4 '14 at 15:42

Well there is multiple solution to this problem ,

• Using delegate:

public bool Validate<T1,T2>(T1 value, T2 compareValue, Func<T1,T2,bool> operation)
{
return operation(value, compareValue);
}
magic.Validate(1, 2, (a, b) => a > b);
magic.Validate("Testing", "Testing", (a, b) => a.Equals(b));


but twp problems with this code is : first your input can be limited , right now you cannot compare more than two values , so you might need to see what can be done to extend this code.

second you can make a switch case to return the right method for comparision.

• Using the Expression which could be more compact and will be cleaner code. I have not tried this yet.

• Avoid using private variable naming with capital letters.

• Avoid giving a name where two capital letters are at start (OMagic), you could write this like OperationMagic.

• Avoid boxing and unboxing (if your operations are small dont worry).

• I just threw some random stuff together for the sake of putting it online. The private vars, and double caps are gone. I also am passing only strings through so there is no more casting. That is the exact solution I was thinking of. I will test it out monday when I get back to work. I am working on a personal project right now. But that is great. If it works I will accept your answer. Thanks. – DeadlyChambers Aug 2 '14 at 18:21
• The main problem with this solution is that .Equals() has an overload that takes an IEqualityComparer as far as I know, which does this in a more detailed way. Regardless, for something like checking if something is greater than something else, I'd suggest just using the < operator by itself. The .Validate() method does not seem to do anything other than hold an actual comparison. – Magus Aug 4 '14 at 14:33
• the whole point of above code is that we can minimize the LOC , without doing anything special , I agree that are other solution too which I have not looked it yet – paritosh Aug 4 '14 at 14:45

After writing up a whole question about how to do this with your validation method, decided to scrap it and show you this:

public static class Validation
{
public static bool Equal(object first, object second)
{
return first.Equals(second);
}

public static bool GreaterThan(int first, int second)
{
return first > second;
}
...
}


This is just a class of validation methods. Just the specific, needed methods.

Converting user input could get a bit annoying, but you'd probably end up with something like this (note that the following is pseudocode):

...
operand = textbox.Text;
result = (bool)typeOf(Magic).GetMethod(combobox.SelectedItem).Invoke(source, operand);
...


This uses reflection, which I am normally loath to do - but this is a situation where it makes the code simpler. You should only ever need to do it when you first take user input, though, so it isn't likely to be a huge issue. You can store the particular invocation and arguments as a delegate if needed for execution later.

• Loath reflection, you're not alone. That is an interesting solution. – DeadlyChambers Aug 4 '14 at 20:19