Reduce casting and better styling - c#

Consider the following (nasty) code:
/// <summary>
/// Calls matching process error code on response.Code
/// </summary>
/// <param name="response">Actually will be of type Response or extend it</param>
/// <returns>true for successful response, false otherwise</returns>
private static bool ProcessErrorCode(object response)
{
bool isOkay = false;
const string unknown = "UNKNOWN";
string errCode = unknown;
if (response.GetType() == typeof(Response<AResponseCode>))
{
AResponseCode code = ((Response<AResponseCode>)response).Code;
isOkay = code == AResponseCode.Ok;
errCode = code.ToString();
}
if (response.GetType() == typeof(Response<BResponseCode>))
{
BResponseCode code = ((Response<BResponseCode>)response).Code;
isOkay = code == BResponseCode.Ok;
errCode = code.ToString();
}
if (response.GetType() == typeof(DataResponse<CResponseCode,string>))
{
CResponseCode code = ((DataResponse<CResponseCode, string>)response).Code;
isOkay = code == CResponseCode.Ok;
errCode = code.ToString();
}
if (isOkay)
{
return true;
}
string msg = "Operation resulted in error code:" + errCode;
LogErrorCode(msg);
return false;
}
I am trying to figure out a way to reduce castings and imrove the method style.
I have no code ownership on Response<TResponseCode>, DataResponse<TResponseCode,string>, AResponseCode, BResponseCode, CResponseCode
response parameter will be of type Response<TResponseCode> or inherit from it (DataResponse<TResponseCode,string> : Response<TResponseCode>)
All *ResponseCode are Enums and they all have an *ResponseCode.Ok entry

You could use a generic subroutine for this:
// Mocking your classes, just to check if it compiles. You don't need this.
class Response<T> {
public T Code { get { return default(T); } }
}
enum AResponseCode { Ok }
enum BResponseCode { Ok }
enum CResponseCode { Ok }
static void LogErrorCode(string msg) { }
private static bool ProcessErrorCode(object response)
{
bool isOkay;
string errCode;
if (!TryProcessErrorCode(response, AResponseCode.Ok, out isOkay, out errCode))
if (!TryProcessErrorCode(response, BResponseCode.Ok, out isOkay, out errCode))
TryProcessErrorCode(response, CResponseCode.Ok, out isOkay, out errCode);
if (isOkay)
{
return true;
}
string msg = "Operation resulted in error code:" + errCode;
LogErrorCode(msg);
return false;
}
// TResponseCode is automatically inferred by passing the okCode
private static bool TryProcessErrorCode<TResponseCode>(
object response, TResponseCode okCode,
out bool isOkay, out string errCode)
{
var resp = response as Response<TResponseCode>;
if (resp == null)
{
isOkay = false;
errCode = "UNKNOWN";
return false;
}
else
{
isOkay = okCode.Equals(resp.Code);
errCode = resp.Code.ToString();
return true;
}
}

Ideally, you'd give Response<TResponseCode> a common interface with an 'OK' function on it. Seeing as you can't, your solution is going to look a bit hacky.
Given that constraint, I'd extract a couple of methods - static bool IsResponseOk(object response) and static string GetResponseError(object response) - which would result in easier to read code, but still not brilliant.

You can get a slightly cleaner solution using generics:
private static void TestErrorCode<TCode>(object response, TCode ok, ref bool isOkay, ref string errCode)
{
Response<TCode> responseTyped = response as Response<TCode>;
if (responseTyped == null)
{
return;
}
TCode code = responseTyped.Code;
isOkay = code.Equals(ok);
errCode = code.ToString();
return;
}
private static bool ProcessErrorCode(object response)
{
bool isOkay = false;
string errCode = "UNKNOWN";
TestErrorCode(response, AResponseCode.Ok, ref isOkay, ref errCode);
TestErrorCode(response, BResponseCode.Ok, ref isOkay, ref errCode);
TestErrorCode(response, CResponseCode.Ok, ref isOkay, ref errCode);
if (isOkay)
{
return true;
}
LogErrorCode("Operation resulted in error code:" + errCode);
return false;
}

I'd swap a switch statement for all the ifs.

From a performance perspective, I'd replace .GetType() == typeof() with the is operator, eg:
if( response is DataResponse<CResponseCode,string> )
The following benchmark shows a performance improvement of roughly 3x on my machine:
var f = new List<string>();
var dummy = 0;
Stopwatch sw = new Stopwatch();
sw.Start();
for(int i=0; i< REPS; i++)
if(f.GetType() == typeof( List<string> )) dummy++;
sw.Stop();
Console.WriteLine(sw.Elapsed);
sw.Reset();
sw.Start();
for(int i=0; i< REPS; i++)
if(f is List<string> ) dummy++;
sw.Stop();
Console.WriteLine(sw.Elapsed);
// Outputs
00:00:00.0750046
00:00:00.0261598

I can't imagine to do something with this without finding person responsible for writing this XResponseZZZ.
Maybe others are smarter than me. But im convinced that you should find the guy and presuade to him that it should be XResponse responsibility to known if specified code is okay and what error message should be thrown. This is C coding style and it is done bad.
I looked at the Heinzi or Daniel generic solutions and I like them most.

Here's a solution with dynamic (can be edited to use reflection instead), untested and not recommended, but short.
It should work identically to your original function:
Since you rely on response.GetType() == typeof(XXX), which is not the same as response is XXX (inheritance is excluded), types.Contains(response.GetType()) is equivalent.
Since you guarantee that all these types have a property Code which is (presumably) an enum type that contains a value Ok, the dynamic portion should always succeed.
The fact that only the eligible types are included means that 'coincidences' cannot happen.
Cons:
Performance?
If the underlying types change, you will not be protected at compile-time.
private static bool ProcessErrorCode(object response)
{
var types = new[] { typeof(Response<AResponseCode>), typeof(Response<BResponseCode>), typeof(DataResponse<CResponseCode, string>)};
var errCode = !types.Contains(response.GetType())
?"UNKNOWN"
:(string)(((dynamic)response).Code.ToString());
if(errCode == "Ok") return true;
LogErrorCode("Operation resulted in error code:" + errCode);
return false;
}

This replaces my old answer as it clearly bombed :) (them's the breaks)
I don't expect this'll do any better - but you might find the approach interesting.
The basic idea is to define a result type that contains your IsOkay and ErrCode values, and then define a dictionary of delegates (keyed by the type of the object that they handle) that you consult. To add new handlers you simply add another delegate to the dictionary.
public class ResponseResult{
public bool IsOkay;
public string ErrCode;
}
public static class ResponseExtracter
{
//STARTING OFF HERE WITH THE NEW VERSION OF YOUR METHOD
public static bool ProcessErrorCode(object response)
{
Func<object, ResponseResult> processor = null;
ResponseResult result = new ResponseResult()
{
IsOkay = false, ErrCode = "UNKNOWN"
};
//try to get processor based on object's type
//then invoke it if we find one.
if (_processors.TryGetValue(response.GetType(), out processor))
result = processor(response);
if (result.IsOkay)
return true;
string msg = "Operation resulted in error code:" + result.ErrCode;
LogErrorCode(msg);
return false;
}
//A lot better no?
//NOW FOR THE INFRASTRUCTURE
static Dictionary<Type, Func<object, ResponseResult>> _processors
= new Dictionary<Type, Func<object, ResponseResult>>();
static ResponseExtracter()
{
//this can be replaced with self-reflection over methods
//with attributes that reference the supported type for
//each method.
_processors.Add(typeof(Response<AResponseCode>), (o) =>
{
AResponseCode code = ((Response<AResponseCode>)o).Code;
return new ResponseResult
{
IsOkay = code == AResponseCode.Ok,
ErrCode = code.ToString()
};
});
_processors.Add(typeof(Response<BResponseCode>), (o) =>
{
BResponseCode code = ((Response<BResponseCode>)o).Code;
return new ResponseResult
{
IsOkay = code == BResponseCode.Ok,
ErrCode = code.ToString()
};
});
_processors.Add(typeof(DataResponse<CResponseCode, string>),
(o) =>
{
CResponseCode code = ((DataResponse<CResponseCode, string>)o).Code;
return new ResponseResult
{
IsOkay = code == CResponseCode.Ok,
ErrCode = code.ToString()
};
});
}
}
Performance-wise it's better than it looks because the Dictionary<Type, TValue> is actually hashing on the integer value that underpins the type's TypeHandle. This is in fact an Int64 - so only the first 32 bits are used, but in practise it's highly unlikely that two types share the same first 32 bits of their handle.

I would be inclined to try to get the main body of code quite simple like this:
/// <summary>
/// Calls matching process error code on response.Code
/// </summary>
/// <param name="response">Actually will be of type Response or extend it</param>
/// <returns>true for successful response, false otherwise</returns>
private static bool ProcessErrorCode(object response)
{
Func<Type, Func<object, string>> process = ...;
var errCode = process(response.GetType())(response);
if (errCode != "Ok")
{
LogErrorCode("Operation resulted in error code:" + errCode);
}
return errCode == "Ok";
}
Then it just becomes a matter of defining the Func<Type, Func<object, string>>. This could be done using a separate method or by dependency injection.
The separate method would look like this:
private static Func<Type, Func<object, string>> _process = null;
private static Func<Type, Func<object, string>> GetProcessFunc()
{
if (_process == null)
{
var d = new Dictionary<Type, Func<object, string>>()
{
{ typeof(Response<AResponseCode>), r => ((Response<AResponseCode>)r).Code.ToString() },
{ typeof(Response<BResponseCode>), r => ((Response<BResponseCode>)r).Code.ToString() },
{ typeof(DataResponse<CResponseCode,string>), r => ((DataResponse<CResponseCode,string>)r).Code.ToString() },
};
_process = t =>
{
if (d.Contains(t))
{
return o => d[t];
}
return o => "UNKNOWN";
};
}
return _process;
}
This still has the same code, per se, but it is now better separated and can be replaced with a dependency injection approach more easily. :-)

Refactored thus, and I'd have been faster if IE hadn't freaked out and reloaded the page spontaneously. :(
I agree with others that this ideally should be gutted and mocked/encapsulated/extended to get where you want, but working within the method as a point of least impact and as an instructional:
bool isOkay = false;
string errCode; // you don't need to default this to anything because it won't be empty if you need to use it
if (response is Response<AResponseCode>) // "is" is a faster and more expressive test
{
var code = (response as Response<AResponseCode>).Code; // "as" is a faster conversion
isOkay = (code == AResponseCode.Ok); // Readability is awesome!
errCode = code.ToString(); // This still sucks
}
else if (response is Response<BResponseCode>) // elsif logically exclusive tests
{
var code = (response as Response<BResponseCode>).Code;
isOkay = code == BResponseCode.Ok;
errCode = code.ToString();
}
else if (response is DataResponse<CResponseCode,string>)
{
var code = (response as DataResponse<CResponseCode, string>).Code;
isOkay = (code == CResponseCode.Ok);
errCode = code.ToString();
}
// Test what you mean to express, i.e. if this isn't ok I need to log it
if (!isOkay)
{
// you don't need a temp variable here...
// and why aren't you just throwing an exception here? Is not being ok a regular unexceptional event, but one you still need to log? Really?
LogErrorCode("Operation resulted in error code:" + errCode);
}
// And try not to return bool literals, it's again unexpressive
return isOkay;

Related

How to return a File in a different method than the main one?

I want to download a file via Results.File(). It works when executing it in the main method (app.MapGet), however returning it in a different method does do nothing. The line where it should send the file is executed in the Debugger, however it does not return, but jumps back to the main method to execute the last return (The one that never should be executed). This last return does indeed return a result.
I have also used several methods like Result.BadRequest(), however nothing is executed when it is not in the main method.
I saw people using IResult as return method but I am not sure whether this is even right.
My guess is maybe the wrong return type or executing a Task or so.
Whole methods:
app.MapGet("/", (HttpContext context) =>
{
if (context.Request.Query.ContainsKey("amount"))
{
if (context.Request.Query["amount"].Count > 1)
{
return Results.BadRequest(new { Error = "The query parameter 'amount' may only be used once." });
}
if (int.TryParse(context.Request.Query["amount"], out int amount))
{
if (amount <= 0)
{
return Results.BadRequest(new { Error = "The specified amount must be greater or equal to 1." });
}
var list = new List<string>();
for (int i = 0; i < amount; i++)
{
list.Add(Ulid.NewUlid().ToString());
}
CheckIfDownload(context, (list, null));
return Results.Json(new { Ulids = list });
}
else
{
return Results.BadRequest(new { Error = "The specified amount is not a valid number." });
}
}
string ulid = Ulid.NewUlid().ToString();
CheckIfDownload(context, (null, ulid));
return Results.Json(new { Ulid = ulid });
});
static IResult? CheckIfDownload(HttpContext context, (List<string>? list, string? single) ulidListOrSingle)
{
if (context.Request.Query.ContainsKey("download"))
{
if (context.Request.Query["download"].Count > 1)
{
return Results.BadRequest(new { Error = "The query parameter 'download' may only be used once." });
}
if (context.Request.Query["download"] == "" || (bool.TryParse(context.Request.Query["download"], out bool download) && download))
{
if (ulidListOrSingle.list != null)
{
return SendJsonFile(JsonSerializer.Serialize(ulidListOrSingle.list));
}
if (ulidListOrSingle.single != null)
{
return SendJsonFile(JsonSerializer.Serialize(ulidListOrSingle.single));
}
return Results.BadRequest(new { Error = "An unknown error occurred." });
}
}
return null;
}
static IResult SendJsonFile(string data)
{
byte[] buffer = Encoding.UTF8.GetBytes(data);
var stream = new MemoryStream(buffer);
return Results.File(stream, "application/json", $"UlidGenerator_{DateTime.Now:MM-dd-yyyy_HH-mm-ss}.json");
}
when you inline an entire method block (not just a single expression), you must return what you want to be the output of the block. In your case you are not capturing the result of SendJsonFile to return it:
app.MapGet("/download", () =>
{
string data = "json data";
var result = SendJsonFile(data);
return result;
});

Multithreaded c# console app to scrape data from sites

I have written an app that goes through our own properties and scraps the data. To make sure I don't run through the same URLs, I am using a MySQL database to store the URL, flag it once its processed. All this was being done in a single thread and it's fine if I had only few thousand entries. But I have few hundred thousand entries that I need to parse so I need to make changes in the code (I am newbie in multithreading in general). I found an example and was trying to copy the style but doesn't seem to work. Anyone know what the issue is with the following code?
EDIT: Sorry didn't mean to make people guess the issue but was stupid of me to include the exception. Here is the exception
"System.InValidCastException: 'Specified cast is not valid.'"
When I start the process it collects the URLs from the database and then never hits DoWork method
//This will get the entries from the database
List<Mappings> items = bot.GetUrlsToProcess(100);
if (items != null)
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
Worker.Done = new Worker.DoneDelegate(WorkerDone);
foreach (var item in items)
{
urls.Add(item.Url);
WaitingTasks.Enqueue(new Task(id => new Worker().DoWork((int)id, item.Url, token), item.Url, token));
}
LaunchTasks();
}
static async void LaunchTasks()
{
// keep checking until we're done
while ((WaitingTasks.Count > 0) || (RunningTasks.Count > 0))
{
// launch tasks when there's room
while ((WaitingTasks.Count > 0) && (RunningTasks.Count < MaxRunningTasks))
{
Task task = WaitingTasks.Dequeue();
lock (RunningTasks) RunningTasks.Add((int)task.AsyncState, task);
task.Start();
}
UpdateConsole();
await Task.Delay(300); // wait before checking again
}
UpdateConsole(); // all done
}
static void UpdateConsole()
{
Console.Write(string.Format("\rwaiting: {0,3:##0} running: {1,3:##0} ", WaitingTasks.Count, RunningTasks.Count));
}
static void WorkerDone(int id)
{
lock (RunningTasks) RunningTasks.Remove(id);
}
public class Worker
{
public delegate void DoneDelegate(int taskId);
public static DoneDelegate Done { private get; set; }
public async void DoWork(object id, string url, CancellationToken token)
{
if (token.IsCancellationRequested) return;
Content obj;
try
{
int tries = 0;
bool IsUrlProcessed = true;
DateTime dtStart = DateTime.Now;
string articleDate = string.Empty;
try
{
ScrapeWeb bot = new ScrapeWeb();
SearchApi searchApi = new SearchApi();
SearchHits searchHits = searchApi.Url(url, 5, 0);
if (searchHits.Hits.Count() == 0)
{
obj = await bot.ReturnArticleObject(url);
if (obj.Code != HttpStatusCode.OK)
{
Console.WriteLine(string.Format("\r Status is {0}", obj.Code));
tries = itemfound.UrlMaxTries + 1;
IsUrlProcessed = false;
itemfound.HttpCode = obj.Code;
}
else
{
string title = obj.Title;
string content = obj.Contents;
string description = obj.Description;
Articles article = new Articles();
article.Site = url.GetSite();
article.Content = content;
article.Title = title;
article.Url = url.ToLower();
article.Description = description;
string strThumbNail = HtmlHelper.GetImageUrl(url, obj.RawResponse);
article.Author = HtmlHelper.GetAuthor(url, obj.RawResponse);
if (!string.IsNullOrEmpty(strThumbNail))
{
//This condition needs to be added to remove ?n=<number> from EP thumbnails
if (strThumbNail.Contains("?"))
{
article.ImageUrl = strThumbNail.Substring(0, strThumbNail.IndexOf("?")).Replace("http:", "https:");
}
else
article.ImageUrl = strThumbNail.Replace("http:", "https:");
}
else
{
article.ImageUrl = string.IsNullOrEmpty(strThumbNail) ? article.Url.GetDefaultImageUrls() : strThumbNail.Replace("http:", "https:");
}
articleDate = HtmlHelper.GetPublishDate(url, obj.RawResponse);
if (string.IsNullOrEmpty(articleDate))
article.Pubdate = DateTime.Now;
else
article.Pubdate = DateTime.Parse(articleDate);
var client = new Index(searchApi);
var result = client.Upsert(article);
itemfound.HttpCode = obj.Code;
if (result)
{
itemfound.DateCreated = DateTime.Parse(articleDate);
itemfound.DateModified = DateTime.Parse(articleDate);
UpdateItem(itemfound);
}
else
{
tries = itemfound.UrlMaxTries + 1;
IsUrlProcessed = false;
itemfound.DateCreated = DateTime.Parse(articleDate);
itemfound.DateModified = DateTime.Parse(articleDate) == null ? DateTime.Now : DateTime.Parse(articleDate);
UpdateItem(itemfound, tries, IsUrlProcessed);
}
}
}
else
{
tries = itemfound.UrlMaxTries + 1;
IsUrlProcessed = true;
itemfound.HttpCode = HttpStatusCode.OK;
itemfound.DateCreated = DateTime.Parse(articleDate);
itemfound.DateModified = DateTime.Parse(articleDate) == null ? DateTime.Now : DateTime.Parse(articleDate);
}
}
catch (Exception e)
{
tries = itemfound.UrlMaxTries + 1;
IsUrlProcessed = false;
itemfound.DateCreated = DateTime.Parse(articleDate);
itemfound.DateModified = DateTime.Parse(articleDate) == null ? DateTime.Now : DateTime.Parse(articleDate);
}
finally
{
DateTime dtEnd = DateTime.Now;
Console.WriteLine(string.Format("\r Total time taken to process items is {0}", (dtEnd - dtStart).TotalSeconds));
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
Done((int)id);
}
}
All this code is based from Best multi-thread approach for multiple web requests this link. Can someone tell me how to get this approach running?
I think the problem is in the way you're creating your tasks:
new Task(id => new Worker().DoWork((int)id, item.Url, token), item.Url, token)
This Task constructor overload expected Action<object> delegate. That means id will be typed as object and you need to cast it back to something useful first.
Parameters
action
Type: System.Action<Object>
The delegate that represents the code to execute in the task.
state
Type: System.Object
An object representing data to be used by the action.
cancellationToken
Type: System.Threading.CancellationToken
-The CancellationToken that that the new task will observe.
You decided to cast it to int by calling (int)id, but you're passing item.Url as the object itself. I can't tell you 100% what the type of Url is but I don't expect Url-named property to be of type int.
Based on what #MarcinJuraszek said I just went back to my code and added an int as I couldn't find another way to resolve it. Here is the change I made
int i=0
foreach (var item in items)
{
urls.Add(item.Url);
WaitingTasks.Enqueue(new Task(id => new Worker().DoWork((string)id, item.Url, token), item.Url, token));
i++;
}

Exceptions in C#

I am trying to write a well-documented code that will be also easy to debug if some exception is handled. Therefore my methods throw exceptions and they're gathered in the log that I can browse. However, it is not really suitable to write complex messages when throwing a new exception. I would like to write a simple utility that would gather:
name of the current class
name of the current method
parameters of the method
Can this be achieved in some easy way? Also, is there a better way to make such logs of exceptions? Perhaps this issue is being solved in a different way, so please share your experience with me :)
An exception already contains this information in its StackTrace.
To get access to it, simply use the public getter:
catch(Exception ex)
{
string trace = ex.StackTrace;
}
If you want to log it, most loggers have an overload which takes an exception. The message and stack trace will be logged.
For example, with log4net, you can use the method void Error(object message, Exception t);:
catch(Exception ex)
{
logger.Error("More details", ex);
}
hi to get the name of the method with signatures the fix is
//get the stack trace
StackTrace stackTrace = new StackTrace();
//the count may vary
MethodBase CallingMethod = stackTrace.GetFrame(2).GetMethod();
//Method called by
string _signatures = MethodInfoExtensions.GetSignature((MethodInfo)CallingMethod));
and the class
public static class MethodInfoExtensions
{
/// <summary>
/// Return the method signature as a string.
/// </summary>
/// <param name="method">The Method</param>
/// <param name="callable">Return as an callable string(public void a(string b) would return a(b))</param>
/// <returns>Method signature</returns>
public static string GetSignature(this MethodInfo method, bool callable = false)
{
var firstParam = true;
var sigBuilder = new StringBuilder();
if (callable == false)
{
if (method.IsPublic)
sigBuilder.Append("public ");
else if (method.IsPrivate)
sigBuilder.Append("private ");
else if (method.IsAssembly)
sigBuilder.Append("internal ");
if (method.IsFamily)
sigBuilder.Append("protected ");
if (method.IsStatic)
sigBuilder.Append("static ");
sigBuilder.Append(TypeName(method.ReturnType));
sigBuilder.Append(' ');
}
sigBuilder.Append(method.Name);
// Add method generics
if (method.IsGenericMethod)
{
sigBuilder.Append("<");
foreach (var g in method.GetGenericArguments())
{
if (firstParam)
firstParam = false;
else
sigBuilder.Append(", ");
sigBuilder.Append(TypeName(g));
}
sigBuilder.Append(">");
}
sigBuilder.Append("(");
firstParam = true;
var secondParam = false;
foreach (var param in method.GetParameters())
{
if (firstParam)
{
firstParam = false;
if (method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false))
{
if (callable)
{
secondParam = true;
continue;
}
sigBuilder.Append("this ");
}
}
else if (secondParam == true)
secondParam = false;
else
sigBuilder.Append(", ");
if (param.ParameterType.IsByRef)
sigBuilder.Append("ref ");
else if (param.IsOut)
sigBuilder.Append("out ");
if (!callable)
{
sigBuilder.Append(TypeName(param.ParameterType));
sigBuilder.Append(' ');
}
sigBuilder.Append(param.Name);
}
sigBuilder.Append(")");
return sigBuilder.ToString();
}
/// <summary>
/// Get full type name with full namespace names
/// </summary>
/// <param name="type">Type. May be generic or nullable</param>
/// <returns>Full type name, fully qualified namespaces</returns>
public static string TypeName(Type type)
{
var nullableType = Nullable.GetUnderlyingType(type);
if (nullableType != null)
return nullableType.Name + "?";
if (!type.IsGenericType)
switch (type.Name)
{
case "String": return "string";
case "Int32": return "int";
case "Decimal": return "decimal";
case "Object": return "object";
case "Void": return "void";
default:
{
return string.IsNullOrWhiteSpace(type.FullName) ? type.Name : type.FullName;
}
}
var sb = new StringBuilder(type.Name.Substring(0,
type.Name.IndexOf('`'))
);
sb.Append('<');
var first = true;
foreach (var t in type.GetGenericArguments())
{
if (!first)
sb.Append(',');
sb.Append(TypeName(t));
first = false;
}
sb.Append('>');
return sb.ToString();
}
}

Callback URL matching logic

I am working on an OAuth type module. In this i have a collection of URLs which are called as Whitelist URLs. I have to check whether the callback URL specified matches with any of these URLs in the collection.
I've written the following code. Please let me know whether i've done it correctly or am i missing some steps. Also, please let me know if i need any kind of refactoring if i want to unit test these methods.
The code is:
public class ValidateURLs
{
public bool MatchRedirectUrl(string requestUrl, IList<string> urlCollection)
{
var requestUri = new Uri(requestUrl);
foreach (var url in urlCollection)
{
var matchUri = new Uri(url);
if (IsDomainMatching(requestUri, matchUri))
{
if (IsPortMatch(requestUri, matchUri))
{
if (IsPathMatch(requestUri, matchUri))
return true;
else
return false;
}
}
}
return false;
}
private bool IsDomainMatching(Uri url1, Uri url2)
{
var result = String.Compare(url1.Host, url2.Host);
if (result == 0)
return true;
else
return false;
}
private bool IsPortMatch(Uri url1, Uri url2)
{
if (url1.Port == url2.Port)
return true;
return false;
}
private bool IsPathMatch(Uri url1, Uri url2)
{
return (url1.PathAndQuery.StartsWith(url2.PathAndQuery) || url2.PathAndQuery.StartsWith(url1.PathAndQuery));
}
}
Thanks in advance.
Regards,
Suyog
Instead of writing all this code, you should look at Uri.Compare
But you also want path.startswith to be part of the comparison. Notice it takes a bitwise enum UriComponents to define which components of the url to compare. So you could replace much of the code with Uri.Compare not comparing path and then have a startsWith path ANDed.
So all your code could be replaced with something like:
Uri.Compare(uri1, uri2, UriComponents.HostAndPort, ...) == 0 &&
(url1.PathAndQueryStartsWith(url2.PathAndQuery) || url.PathAndQueryStartsWith(...));
On a side note, code in this form:
var result = String.Compare(url1.Host, url2.Host);
if (result == 0)
return true;
else
return false;
Can simply be written as:
return String.Compare(url1.Host, url2.Host) == 0;
You should also do case insensitive compares with: StringComparison.OrdinalIgnoreCase

C# short if statement

Is there a way to do this in C# without making a new method to overload for every var type there is?
$box = !empty($toy) : $toy ? "";
The only ways I can think of to do it is either:
if (toy != null)
{
box += toy;
}
or this:
public string emptyFilter(string s) ...
public int emptyFilter(int i) ...
public bool emptyFilter(bool b) ...
public object emptyFilter(object o)
{
try
{
if (o != null)
{
return o.ToString();
}
else
{
return "";
}
}
catch (Exception ex)
{
return "exception thrown":
}
}
box += this.emptyFilter(toy);
I basically wanna check to make sure that the variable/property is set/not empty/exists/has value/etc... and return it or "" without some ridiculous about of code like above.
You could use the conditional operator (?:):
string box = (toy != null) ? toy.ToString() : "";
return variable ?? default_value;
That what you're going for? I'm a little confused considering you're showing PHP code and tag this with C#.
There's also the Nullable<T> type you can use.
How bout an extender class?
public static class ToStringExtender
{
public static String ToStringExt(this Object myObj)
{
return myObj != null ? myObj.ToString() : String.Empty;
}
}
var myobject = foo.ToStringExt()
DEMO
I'm not sure of what he wants, BUT:
string str = String.Empty;
str += true;
str += 5;
str += new object();
str += null;
This is perfectly legal. For each one adition the ToString() will be called. For null, simply nothing will be added.
The value of str at the end: True5System.Object
or,
var s = (toy?? "").ToString();
or
var s = (toy?? string.Empty).ToString();
i think there may be a slight misunderstanding about how var is used; but that's a separate topic.
maybe this below will help:
box += (toy ?? "").ToString();

Categories

Resources