I have the following function:
public void Test(string testString)
{
//Do Stuff
}
At some points in my code, I have to repeatedly check if the parameter is empty string/null/whitespace to skip the body method. The usual ways I've done this till now, are the following:
public void Test(string testString)
{
if(!string.IsNullOrWhiteSpace(testString))
{
//Do Stuff only if string has text in it.
}
}
Or
public void Test(string testString)
{
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
Is there a way to create a custom attribute that checks if the parameter of the function is empty etc, to skip the method? I've had some experiece (basic stuff), with custom attributes, but I can't figure out a way to make the attribute skip the method body.
The ideal end product of the implementation would be the following:
[SkipIfEmptyParameter]
public void Test(string testString)
{
//Do Stuff only if string has text in it.
}
Of course, any suggestion is welcome that helps minimize the recurring code if the attribute implementation is not possible.
Edit: Example of the problem I want to solve.
I have the following methods. I get from Microsoft Test Manager, some parameters that our test scenario are expecting (what the values should be). There is a SharedStep implementation that asserts the user's info:
public void AssertUser(UserDTO expectedUserInfo)
{
VerifyUserName(expectedUserInfo.name);
VerifyUserSurname(expectedUserInfo.surname);
VerifyUserAge(expectedUserInfo.age);
VerifyUserHeight(expectedUserInfo.height);
}
private void VerifyUserName(string name)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's name at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserSurname(string surname)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's surname at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserAge(string age)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's age at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserHeight(string height)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's height at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
The "Do Stuff" contain Selenium implementation that handle WebElements and might be time consuming, so if we don't want to validate that specific value, we just skip the whole method.
Now, when creating the scenarios over to Microsoft Test Manager, the shared steps allows the tester to decide what elements of the page will be validated. If some of the parameters are empty, then the code just skips the blocks and goes to w/e validation the user wants (still, the implementation is for every info the user has, but we just assign value to each parameter we want to test, and every parameter that does not have a value, just gets it's method body skipped).
The problem is, if I want to change the condition of skipping the method, I will have to go to each method and manually change the IF statement. Hence why I though it might be a good idea to have an attribute for every method that validates information.
P.S. I'm talking about hundreds of methods that have the IF implementation at the start.
The only way that I know that this can be done using attributes is aspect oriented programming using a product like post sharp and method interception. Alternatively if the methods are defined in an interface this can also be done by using RealProxy but seems more than a little overkill.
The way you are doing it is actually pretty good. But as Evk pointed out in the comments: You should extract the "skip checking" into a separate method, especially if the check is always the same and needs to be changed globally. Using an attribute would solve the problem, but is a little complicated to use.
Instead, take a look at the code below. Looks pretty clear, doesn't it? Don't use too many comments (and don't copy-paste them into every method, that is of no use). This way, you have the same benefits as if you would use a custom attribute but without the ugliness of using reflection.
public void AssertUser(UserDTO expectedUserInfo)
{
VerifyUserName(expectedUserInfo.name);
VerifyUserSurname(expectedUserInfo.surname);
VerifyUserAge(expectedUserInfo.age);
VerifyUserHeight(expectedUserInfo.height);
}
private void VerifyUserName(string name)
{
if (ShouldSkipValidation(name)) return;
// code here...
}
private void VerifyUserSurname(string surname)
{
if (ShouldSkipValidation(surname)) return;
// code here...
}
private void VerifyUserAge(string age)
{
if (ShouldSkipValidation(age)) return;
// code here...
}
private void VerifyUserHeight(string height)
{
if (ShouldSkipValidation(height)) return;
// code here...
}
// The MTM scenario does not want to validate values that satisfy the check below
private bool ShouldSkipValidation(string value)
{
return string.IsNullOrWhiteSpace(value) || value == "<>";
}
I don't think attributes make it possible to achieve what you are trying to achieve.
But you can use a custom method invoker instead:
static void Main(string[] args)
{
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), null);
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "");
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "abc");
// RESULT:
// Trying to invoke action...
// Trying to invoke action...
// Trying to invoke action...
// I have been invoked!
}
static void InvokeIfNotNullOrWhitespace(Action<string> action, string inputString)
{
Console.WriteLine("Trying to invoke action...");
if(!string.IsNullOrWhiteSpace(inputString))
action.DynamicInvoke(inputString);
}
static void TestMethod(string input)
{
Console.WriteLine("I have been invoked!");
}
The reason why I think attributes won't work is because they can't control what is going on inside the method. Instead, "other external things" can look at those attributes and decide what to do.
To achieve what you are trying to achieve, an "external thing" would need to look at the attribute and decide if it is executed or not. This would be equivalent to what I wrote: an external invoker that unifies the "check string validity" procedure.
Here are my 4 cents on this,
Calling an attribute involves reflection, already a bad idea as
you need to find out if the attribute is set;
You're avoiding a "1 liner" in your code that actually is quite
easy to type;
Use method overloading;
You can use Aspect oriented programming that will basically inject the below samples in your code at compile time. You can control the way this works with annotations and would not have a negative effect on the generated runtime.
Here are some variations:
//1
if(string.IsNullOrEmpty(testString))
return;
//2
if(string.IsNullOrEmpty(testString) ||string.IsNullOrWhiteSpace(testString) )
return;
When going for 3 just make sure you do not mix returning null, or boolean true/false based on the "missing" text. Only you know how your code should flow.
Perhaps you are looking for method overloading
you can do that by creating 2 methods with the same name in the same class.
You can call the empty MyMethod() from the MyMethod(with string) so you do not duplicate the logic.
return string.IsNullOrEmpty(testString)?MyMethod():MyMethod(testString);
Related
I am using delegates and events to pass data around in my application, but want the triggering of 1 event to pass different sets of data to different places.
Problem
I have a main class which performs some work. Once the work is complete, I want it to notify a number of other classes (including the UI) so that other actions can be carried out. The information that the other classes needs is different.
Example
Main.cs - Performs an action and wants to update the UI, send a text message and write to a log file.
UI updates a DataGrid so needs the individual fields.
The log file writer needs all the whole line as an array / List.
The text message code needs the Line, LineNumber and FileName, but as a tab delimited string.
The below all works correctly when I am only trying to update the UI, but when I try to send different information to different places then I run into errors.
I have tried creating different extensions of EventArgs, but if I try to declare 2 delegates with different signatures then I get an error message.
Any help would be much appreciated.
FrmMain.cs
Main main = new Main();
main.PatternFound += OnPatternFound;
main.DoSomeWork();
private void OnPatternFound(object source, LineEventArgs e)
{
UpdateDataGrid(e.Line, e.FileName, e.LineNumber);
}
private void UpdateDataGrid(string line, string file, int lineNumber)
{
if (InvokeRequired)
{
Invoke(new Action<string, string, int>(UpdateDataGrid), line, file, lineNumber);
}
else
{
dgResults.Rows.Add(line, file, lineNumber);
}
}
Main.cs
public delegate void PatternFoundEventHandler(object sender, LineEventArgs e);
public event PatternFoundEventHandler PatternFound;
protected virtual void OnPatternFound(string line, string fileName, int lineNumber)
{
PatternFound?.Invoke(this, new LineEventArgs { Line = line, FileName = fileName, LineNumber = lineNumber });
}
public void DoSomeWork()
{
//Finished my work
OnPatternFound(line, file, lineNumber);
}
LineEventArgs.cs
public class LineEventArgs : EventArgs
{
public string Line { get; set; }
public string FileName { get; set; }
public int LineNumber { get; set; }
}
What you are trying to achieve is possibly not a good approach for several reasons. Your decided to stick to events which means you decided to do what is called "inversion of control".
You implemented your main class in a way that says: "I am doing some sort of pattern matching and I will tell whoever is interested what I found and I am doing it in the way my event-args implementation defines." As a result it's now up to the subscribers to take this information as is or leave it.
Strictly spoken, what you said...
Performs an action and wants to update the UI, send a text message and write to a log file.
...is not what you implemented, because the main class does nothing of this. Anyway, in my opinion it is a viable solution to keep it event-driven, but then you would need to change your upstream code.
You could for example attach three different event handlers to this single event. Every handler would then have to transform the data in a format it needs: The logging handler would have to transform it to an array, the UI handler would have to concatenate it and so on.
The other alternative would be that you have one handler and dispatch to three different methods, like the OnPatternFound method would call a UpdateUI method and a Log method and so on.
Lastly you could also get rid of inversion of control and move your logic to the main class, but I would not recommend it! Your approach is good, but you should just not try to invoke the same event in three different ways. That's up to the subscribers.
I have a validation method which I call in a loop.
I want to call "continue" if the validation fails.
Is there a way to call "continue" from the validation method ?
I just don't want to call "continue" in so many places in the loop...
No, flow control statements only affect the blocks within which they are defined. The only built-in way to alter control flow from further up the stack like that is an exception, which is definitely the wrong mechanism for what you are doing.
If you are bothered by all the continues, I suggest you consider moving towards a more declarative way of thinking. Define the body of your validation loop like so:
bool IsValid(Foo foo) {
if (Condition1(foo)) {
return false;
}
if (Condition2(foo)) {
return false;
}
// ... and so on
}
and then validate like this:
if (!foos.All(IsValid)) {
// One of your foos is invalid
}
the LINQ extension methods All and Any will break execution as soon as they can, meaning that All will stop when it finds the first one that doesn't satisfy the condition and Any will stop when it finds the first one that does.
You have a lot of continues in your cycle and it becomes bothering. You cannot continue from the external method, as it is out of scope. There are several solutions actually though:
You can return a boolean value from your validation methods and then use it as such:
if (!IsValid()) {
continue;
}
It is not helpful though, because you will still have continues.
You can put your validations at the start of the cycle and you can use a flag to determine whether the iteration should step out, initialized by false:
while (myCondition) {
stepOut = false;
//validation region, you set stepOut to false if a validation fails
if (!stepOut) {
//operations
}
}
You can wrap all the validation call into a method, let's call it myValidation and then:
while (myCondition) {
if (myValidation()) {
//operations
}
}
or
while (myCondition) {
if (!IsValid()) {
//continue
}
}
You can throw an Exception, but DON'T do that.
Just return false in your validation method wherever it should return, then check if the validation method returns false, break out of loop in caller function.
Why Not ?
Golden Rule in Programming : "There is always a way".
C++ lets you inline Assembly Language syntax. Similar to it, C# supports it too. Let me consider your example.
void method1(){
foreach(var x in y)
{
Validate(x);
...
//Your other logic
...
EndOfLoop:
;
}
}
..
..
void Validate(T x)
{
#if IL
br EndOfLoop
#endif
}
//End Of Code
This will "jump" to the "EndOfLoop" Label from anywhere within your Code. This could be a bad practice depending on your code though..
this is the best way I can think of doing this. Could you give me so hints as to whether this is the correct way or if there is a more efficient way of doing it.
My situation is:
Each time the frame is Update()'ed (Like in XNA) I want to check if something has happened.. Like if the timer for that screen has been running for over 2000 milliseconds. But I only want it to fire once, not every time the frame is updated. This would cause a problem:
if(totalMilliseconds > 2000)
{
this.Fader.FadeIn();
}
So I came up with this method that I have implemented in the GameScreen class that looks like this:
public bool RunOnce(string Alias, bool IsTrue)
{
if (!this.Bools.ContainsKey(Alias))
this.Bools.Add(Alias, false);
if (IsTrue && !this.Bools[Alias])
{
this.Bools[Alias] = true;
return true;
}
else
return false;
}
This basically checks if the passed if statement boolean is true, if it is then it fires once and not again unless the Bool["Alias"] is set back to false. I use it like this:
if(this.RunOnce("fadeInStarted", totalMilliseconds > 2000))
{
this.Fader.FadeIn();
}
This will then only run one time and I think is quite easily readable code-wise.
The reason I have posted this is for two reasons.. Firstly because I wanted to show how I have overcome the problem as it may be of some help to others who had the same problem.. And secondly to see if I have missed an obvious way of doing this without creating a manual method for it, or if it could be done more efficiently.
Your method is interesting, I don't see a problem with it, you've essentially created a new programming construct.
I haven't encountered this situation a lot so what I have done in this situation is always start with the untidy approach:
bool _hasFadedIn = false;
.
if(totalMilliseconds > 2000 && !_hasFadedIn)
{
this.Fader.FadeIn();
_hasFadedIn = true;
}
And 90% of the time I leave it like that. I only change things if the class starts growing too big. What I would do then is this:
_faderControl.Update(totalMilliseconds);
Put the logic for fader control into a separate class, so:
class FaderControl
{
bool _hasFadedIn=false;
public void Update(int totalMilliseconds)
{
if (_hasFadedIn)
return;
if (totalMilliseconds <= 2000)
return;
this.Fader.FadeIn();
_hasFadedIn=true;
}
}
It can be modified to make it configurable, like reseting, setting "start", "end", fadein time, or also controlling fadeout too.
Here's how I would approach this problem.
These are your requirements:
You have arbitrary pieces of logic which you want to execute inside of your Update().
The logic in question has a predicate associated with it which determines whether the action is ready to execute.
The action should execute at most once.
The core concept here is "action with an associated predicate," so create a data structure which represents that concept:
public class ConditionalAction
{
public ConditionalAction(Action action, Func<Boolean> predicate)
{
this.Action = action;
this.Predicate = predicate;
}
public Action Action { get; private set; }
public Func<Boolean> Predicate { get; private set; }
}
So now, your example becomes
var action = new ConditionalAction(
() => this.Fader.FadeIn(),
() => totalMilliseconds > 2000);
In your Update() you need something that can execute these conditional actions:
public void Update(GameTime time)
{
// for each conditional action that hasn't run yet:
// check the action's predicate
// if true:
// execute action
// remove action from list of pending actions
}
Because their predicates are probably unrelated, actions don't necessarily run in order. So this isn't a simple queue of actions. It's a list of actions from which actions can be removed in arbitrary order.
I'm going to implement this as a linked list in order to demonstrate the concept, but that's probably not the best way to implement this in production code. Linked lists allocate memory on the managed heap, which is generally something to be avoided in XNA. However, coming up with a better data structure for this purpose is an exercise best left for another day.
private readonly LinkedList<ConditionalAction> pendingConditionalActions =
new LinkedList<ConditionalAction>();
public void Update(GameTime time)
{
for (var current = pendingConditionalActions.First; current != null; current = current.Next)
{
if (current.Value.Predicate())
{
current.Value.Action();
pendingConditionalActions.Remove(current);
}
}
}
public void RegisterConditionalAction(ConditionalAction action)
{
pendingConditionalActions.AddLast(action);
}
Registered actions will wait until their predicates become true, at which point they will be executed and removed from the list of pending actions, ensuring that they only run once.
I'm in the process of developing my first Windows Phone 7 Application. I'm freshfaced to Silverlight, C# and the whole .NET Scene, but I like to think I'm making decent progress.
I know from various code examples, I can set the tile using ShellTile. I know I can pass through params with the URI (Like this example):
ShellTile.Create(new Uri("/MainPage.xaml?DefaultTitle=FromSecondaryTile", UriKind.Relative), tile );
Can anyone point me in the direction (or explain) how I can handle arguments passed from the tile? So, when the tile's open, I'd like to open a certain part of the application.
For the record, I'm aware I could create a separate page for each one to handle it that way, but I can see that getting messy fast :)
Thanks!
Mike
A way I've found that works well for my particular purpose, is the same means of passing values between xaml pages, which is simply to pass them through in the query string:
NavigationContext.QueryString["XXXXX"].ToString();
Where XXXXX is the name in the key/name pair.
You can either set the url to a seperate page (like OtherPage.xaml) or you can use the supplied URI, and change the page/view in the OnNavigatedTo override.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
...
}
Here the NavigationEventArgs will provide you with the navigation args you supplied, as a regular dictionary. From those, you can decide what to do then.
Also, you can make life easier with a simple extension (here specialized with a overload for a integer key, since I personally prefer use them for identifiers)
namespace System.Windows.Navigation
{
public static class NavigationExtensions
{
public static int? TryGetKey(this NavigationContext source, string key)
{
if (source.QueryString.ContainsKey(key))
{
string value = source.QueryString[key];
int result = 0;
if (int.TryParse(value, out result))
{
return result;
}
}
return null;
}
public static string TryGetStringKey(this NavigationContext source, string key)
{
if (source.QueryString.ContainsKey(key))
{
return source.QueryString[key];
}
return null;
}
}
}
I use the following code to Invoke and access properties on my from from a different thread.
public static void PFA(Action<frmain> action)
{
var form = Form.ActiveForm as frmain;
if (form != null)
{
form.PerformAction(action);
}
}
public void PerformAction(Action<frmain> action)
{
if (InvokeRequired)
Invoke(action, this);
else
action(this);
}
My Question:
If I call PFA(form => form.Richbox1.Text = "Test") - I want PFA() to check if the action is (Richbox1.Text) and if so then Add "\n" to the text("Test").
The Idea is to call
PFA(form => form.Richbox1.Text = "Test");
instead of
PFA(form => form.Richbox1.Text = "Test\n");
In other words I want to add a new line automaticly if the action is "Richbox1.Text ="
How I do that? I never worked with actions before.
What if you did:
PFA(form => UpdateTextBox(form.Richbox1,"Test"));
public void UpdateTextBox(RichTextBox box,string text)
{
if (box.Name=="Richbox1")
{
text+="\n";
}
box.AppendText(text);
}
Your not going to be able to look inside the action and determine it's using a specific cotnrol from outside of the action. So either you need to add the \n before you call PFA, or have PFA call a function which will do what you want, or have PFA implement the logic.
You can add an extension method to do the trick. Try the following.
public static void AddNewLineIfMatch(this RichTextBox rtb, string toMatch) {
if ( rtb.Text == toMatch ) {
rtb.AppendText("\n");
}
}
PFDA(() => form.Richbox1.AddNewLineIfMatch("Test"));
EDIT Used the AppendText method instead of Text+=
You can't do this the way you want. PFA function can not check what's is inside your delegate. Think how you can solve your task another way.
[offtopic]
PS. Also, your naming convention is not very good. "PFA" doesn't explain what the function does and as for "frmain" - usually class names start with capital letter.
[/offtopic]
UPDATE:
I would do it a little bit better, than Josh offered:
PFA(form => SetControlText(form.Richbox1, "Test"));
public void SetControlText(Control control, string text)
{
control.Text = text;
// choose control type for which you want to add new line
if(control is RichTextbox || control is TextBox || control is ... )
control.Text += Environment.NewLine;
}
You could accomplish this by moving from Action to Expression>. Then you can look at what's happening in the method like so
public static void PFA(Expression<Action<frmain>> expression) {
// this will give you form.RichTextBox1
var targetFormProperty = (MemberAccessExpression)expression.Body;
// this only works for your example given. this gives you RichTextBox1.Text
var textProperty = (MemberAccessExpression)targetFormProperty.Expression;
// this is how you would run your action like normal
var action = expression.Compile();
action(); // invoke action (you would want to wrap this in the invoke check)
}
This gives you the info you need to figure out the property, but not how to append the \n. I'll leave this up to you to find out. I think this is overkill here, but who knows, maybe this could help you or someone else, or even inspire a nice solution.
A nice solution i could possibly think of where you could reuse this functionality is like a rule engine where you might compare what the property being accessed is and run an action right after it, etc.