I hope someone can help with this. For a few years now, I've been iterating through my searchresult using a LOT of If statements to populate all of the properties in my class. There are over 300 properties that I need to populate.. but that is an awful lot of if statements. As an example, this is what I mean:
var myCon = StarfishLDAPCon.CreateDirectoryEntry(objectContainer, whichCM);
var ds = new DirectorySearcher(myCon);
ds.Filter = "(deftyAgentID=07629)";
var result = ds.FindOne();
AgentID returnValue = new AgentID();
if (result.Properties.Contains("deftyAgentID"))
{
returnValue.DeftyAgentID = result.Properties["deftyAgentID"][0].ToString();
}
if (result.Properties.Contains("deftySecuritycode"))
{
returnValue.DeftyAgentID = result.Properties["deftySecuritycode"][0].ToString();
}
if (result.Properties.Contains("deftyAgentACWAgentConsdrdIdle"))
{
returnValue.DeftyAgentACWAgentConsdrdIdle = result.Properties["deftyAgentACWAgentConsdrdIdle"][0].ToString();
}
I have over 300 of those if statements. I'm hoping there's some cool way to do this without all those if statements? Anyone have any ideas?
Thanks for any help!
Dave M.
Well pretty simple - just write a small extension method like this:
public static class SearchResultExtension
{
public string GetPropertyValue(this SearchResult result, string propName)
{
if (result == null || result.Properties == null)
{
return null;
}
if (result.Properties.Contains(propName))
{
return result.Properties[propName][0].ToString();
}
return null;
}
}
Now you can handle the 80% "normal" cases like this:
SearchResult result = ds.FindOne();
AgentID returnValue = new AgentID();
returnValue.DeftyAgentID = result.GetPropertyValue("deftyAgentID");
returnValue.DeftySecurityCode = result.GetPropertyValue("deftySecuritycode");
returnValue.DeftyAgentACWAgentConsdrdIdle = result.GetPropertyValue("deftyAgentACWAgentConsdrdIdle");
and so forth. Any cases that should not return the first element of the Properties collection as a string need to be handled separately, obviously
Reshaper said the left hand side of ?? was never null even though its type is int?
_savedMediaFileId = mediaFile.MediaFileId ?? _savedMediaFileId;
The auto refactor "remove unreachable code" turned it into this:
_savedMediaFileId = (int) mediaFile.MediaFileId;
Is that right or is Resharper making a mistake here?
My idea was that since int? is nullable, then then I could use ?? to keep the existing value in the case it is null.
Here's my unit test (in progress)
[TestClass]
public class MediaRepositoryTest
{
private const string SiteId = "3";
private const string ConnectionString =
#"Data Source=dvmind\mssqlsites;Database=***********;User Name=sa;Password=**************";
private string _mediaSourceName = "TestMediaSourceName";
private string _mediaTypeName = "TestMediaTypeName";
private string _mediaSourceAddress = "TestMediaSourceAddress";
private string _mediaFileAddress = "TestMediaFileAddress";
private int _savedMediaFileId = 0;
private string GetGuidString()
{
return Convert.ToBase64String(Guid.NewGuid().ToByteArray());
}
[TestInitialize]
public void TestInitialize()
{
_mediaSourceName = _mediaSourceName + GetGuidString();
_mediaTypeName = _mediaTypeName + GetGuidString();
_mediaSourceAddress = _mediaSourceAddress + GetGuidString();
_mediaFileAddress = _mediaFileAddress + GetGuidString();
}
[TestCleanup]
public void TestCleanup()
{
using (var db = new SiteContext(ConnectionString))
{
if (_savedMediaFileId != 0)
{
(from c in db.MediaFiles where c.MediaFileId == _savedMediaFileId select c).ToList()
.ForEach(c => db.MediaFiles.Remove(c));
}
(from c in db.MediaSources where c.MediaSourceName == _mediaSourceName select c).ToList()
.ForEach(c => db.MediaSources.Remove(c));
(from c in db.MediaTypes where c.MediaTypeName == _mediaTypeName select c).ToList()
.ForEach(c => db.MediaTypes.Remove(c));
}
}
[TestMethod]
public void SaveMediaTest()
{
var mediaSource = new MediaSource
{
MediaSourceName = _mediaSourceName,
MediaSourceAddress = _mediaSourceAddress
};
var mediaType = new MediaType
{
MediaTypeName = _mediaTypeName
};
var mediaFile = new MediaFile
{
SiteId = SiteId,
MediaFileAddress = _mediaFileAddress,
MediaSource = mediaSource,
MediaType = mediaType
};
var connectionStringProvider =
Mock.Of<IConnectionStringProvider>(c => c.GetConnectionString() == ConnectionString);
var repository = new MediaRepository(connectionStringProvider);
Assert.IsTrue(mediaFile.MediaFileId == 0);
repository.SaveMedia(mediaFile);
Assert.IsTrue(mediaFile.MediaFileId != 0);
_savedMediaFileId = mediaFile.MediaFileId ?? _savedMediaFileId;
//using (var db = new SiteContext(ConnectionString))
//{
//}
}
Now that you've posted a complete example, I think the reason you are getting unreachable code, is due to the Assert conditions that precede this line;
Assert.IsTrue(mediaFile.MediaFileId == 0);
If mediaFile.MediaFileId is null, the program exits on this line, if its not, then the warning is correct; mediaFile.MediaFileId cannot be null on the line you highlight;
_savedMediaFileId = mediaFile.MediaFileId ?? _savedMediaFileId;
Also, if the definition of SaveMedia took a ref MediaFile that would also impact the warning, because it is then possible (as far as ReSharper is concerned) that the value is changed again to Null by;
repository.SaveMedia(mediaFile);
Either of these changes will impact the presence of the warning.
ReSharper is likely inferring here that mediaFile.MediaFileId can never have the value null even though the type is int?. Hence it's suggesting that you skip the null check entirely and go straight for the value
A clearer example is the following
string s = "hello world";
if (s != null) {
...
}
In this case s can be null practically because it is of type string and null is a valid value. However in this specific context s can never be null hence ReSharper would flag this check as unnecessary
This is a bit of a guess, but I think what's happening here (based on MSDN
When you declare someting int?, it doesn't create a reference type that can be null. Instead, it creates Nullable<T> which is a struct meaning it cannot be Null b/c it is a value type. That struct besides the value contains a boolean flag that tells it if it is null of if value is valid.
Hence, doing int? ?? is essentially testing a struct for null value which it can never be. It does not test Nullable<T>.HasValue which is a way to test if is "null" or not.
Hence the ReSharper complaint.
I designed my webpage to read a data string then display the results on labels in an html table. I am attempting to highlight the row that my database reads as a current order. My only problem is only one record is set to be active but they all highlight as if they were active. I use an array to set my data and I also use the label to get the ID I need (all is in code below). I have posted my method and where I use it in the asp page load. How can I fix my method to return correctly?
The implementing of the method in page load
if (lineData.IsCurrentOrderFind(L68.Text))
{
myTable.Rows[1].Cells[0].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[1].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[2].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[3].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[4].BgColor = "#FE2E2E";
}
Here is method that label above gets passed to
public bool IsCurrentOrderFind(string itemNumber)
{
StringBuilder sqlString = new StringBuilder();
sqlString.Append("SELECT * ");
sqlString.Append("FROM WorkOrder ");
sqlString.Append("WHERE LineNumber = " + ConfigurationManager.AppSettings["Line"] + " AND LineCompleted = 0 AND (ScaleGroup LIKE '%1' OR ScaleGroup LIKE '%3') ");
sqlString.Append(" AND CaseGenNum6 = #CaseGenNum6");
SqlDataReader reader = null;
SqlConnection dbConn = App_Code.DBHelper.getConnection();
SqlParameter[] parameters = new SqlParameter[] { new SqlParameter("#CaseGenNum6", itemNumber) };
try
{
reader = App_Code.DBHelper.executeQuery(dbConn, sqlString.ToString(), parameters);
while (reader.Read())
{
IsCurrentOrder = (reader["IsCurrentOrder"] != DBNull.Value && !string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())) ? true : false;
}
reader.Close();
reader.Dispose();
dbConn.Close();
dbConn.Dispose();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (dbConn != null)
{
try { dbConn.Close(); dbConn.Dispose(); }
catch { }
}
if (reader != null)
{
try { reader.Close(); reader.Dispose(); }
catch { }
}
}
if (IsCurrentOrder == true) I realize this is not necessary
{
return true;
}
else
{
return false;
}
}
The problem could be with this expression:
!string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())
Instead of calling ToString(), try simply casting it to a string:
!string.IsNullOrEmpty((string)reader["IsCurrentOrder"])
Possibly even better (the previous line might throw an exception if it's not really a string):
!string.IsNullOrEmpty(reader["IsCurrentOrder"] as string)
The reason being is that if the string is really null, calling ToString() will return a non-null string "null".
IsCurrentOrder is not declared locally. It seems to be declared at a higher scope. When you enter this function, nothing is initializing the variable (back to false). So, it is remaining at its last setting. Try this code instead:
public bool IsCurrentOrderFind(string itemNumber)
{
bool IsCurrentOrder = false;
//and the rest of your source code
the line
IsCurrentOrder = (reader["IsCurrentOrder"] != DBNull.Value && !string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())) ? true : false;
}
It's not actually checking the value of the field, only that it's not null or empty.
Try
if(
(reader["IsCurrentOrder"] != DBNull.Value
&&
!string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString()))
)
{
IsCurrentOrder = reader["IsCurrentOrder"];
}
else
IsCurrentOrder = false;
I think there is a lot of refactoring you could do to this method though that will simplify the logic.
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;
is there a better way then a try/catch to parse numbers and datetimes without crashing the page?
if they are not valid numbers/datetimes they should be null.
here is what I've got so far:
long id = null;
try{
id = Int64.Parse(Request.QueryString["id"]);
}catch(Exception e){}
DateTime time = null;
try{
time = DateTime.Parse(Request.QueryString["time"]);
}catch(Exception e){}
int tempInt = 0;
if(int.TryParse(Request["Id"], out tempInt))
//it's good!!
Likewise, for the date it's "DateTime.TryParse"
edit
To fully mimic what your code is doing, you'd have this:
long? id = null; DateTime? time = null;
long tempLong; DateTime tempDate;
if(long.TryParse(Request["id"], out tempLong))
id = tempLong;
if(DateTime.TryParse(Request["time"], out tempDate))
time = tempDate;
Use TryParse instead of Parse.
TryParse doesn't throw and is good for situations like this, where the input is not necessarily trusted and you do not want an exception thrown.
Have you noticed TryParse?
long id = -1;
if(Int64.TryParse(Request.QueryString["id"] ?? "", out id))
// is valid...
You can use TryParse:
Int64.TryParse
DateTime.TryParse
This is how I usually do in my projects:
public long? ClientId
{
get
{
long? result = null;
if (Request.QueryString[QueryStringConstants.ClientId] != null)
result = Convert.ToInt64(Request.QueryString[QueryStringConstants.ClientId]);
return result;
}
}
public DateTime? ItemPurchasedDate
{
get
{
DateTime? result = null;
if (Request.QueryString[QueryStringConstants.ItemPurchasedDate] != null)
result = Convert.ToDateTime(Request.QueryString[QueryStringConstants.ItemPurchasedDate]);
return result;
}
}
And I have defined my static class QueryStringConstants like this
public static class QueryStringConstants
{
public static string ClientId = "clientId";
public static string ItemPurchasedDate = "itemPurchasedDate";
}