netcore - elegant way to check var A or B is not null/empty to get it - .net-core

Is there any operator like || to get first non-null/empty value like we can do in other languages?
I can achieve the same using ifs:
public static void Main(string[] args)
{
string a = "value";
string b = null;
string c = b;
if (string.IsNullOrEmpty(c)) {
c = a;
if(string.IsNullOrEmpty(c)){
throw new System.Exception("...");
}
}
}
If I have more variables to check, it will become a mess. Is there other way to achieve it?

You can use extensions for this
public static string IfNullOrEmptyGet(this string str, string newValue)
{
if (!string.IsNullOrEmpty(str))
return str;
if (string.IsNullOrEmpty(newValue))
throw new Exception($"{nameof(newValue)} is null or empty");
else
return newValue;
}
and use like c = c.IfNullOrEmptyGet(a)

Related

Xunit CSV streamReader.ReadToEnd returns System.ArgumentOutOfRangeException

I would like to evaluate a CSV data series with Xunit.
For this I need to read in a string consisting of int, bool, double and others.
With the following code, the transfer basically works for one row.
But since I want to test for predecessor values, I need a whole CSV file for evaluation.
My [Theory] works with InlineData without errors.
But when I read in a CSV file, the CSVDataHandler gives a System.ArgumentOutOfRangeException!
I can't find a solution for the error and ask for support.
Thanks a lot!
[Theory, CSVDataHandler(false, "C:\\MyTestData.txt", Skip = "")]
public void TestData(int[] newLine, int[] GetInt, bool[] GetBool)
{
for (int i = 0; i < newLine.Length; i++)
{
output.WriteLine("newLine {0}", newLine[i]);
output.WriteLine("GetInt {0}", GetInt[i]);
output.WriteLine("GetBool {0}", GetBool[i]);
}
}
[DataDiscoverer("Xunit.Sdk.DataDiscoverer", "xunit.core")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class DataArribute : Attribute
{
public abstract IEnumerable<object> GetData(MethodInfo methodInfo);
public virtual string? Skip { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : DataAttribute
{
public CSVDataHandler(bool hasHeaders, string pathCSV)
{
this.hasHeaders = hasHeaders;
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
var methodParameters = methodInfo.GetParameters();
var paramterTypes = methodParameters.Select(p => p.ParameterType).ToArray();
using (var streamReader = new StreamReader(pathCSV))
{
if (hasHeaders) { streamReader.ReadLine(); }
string csvLine = string.Empty;
// ReadLine ++
//while ((csvLine = streamReader.ReadLine()) != null)
//{
// var csvRow = csvLine.Split(',');
// yield return ConvertCsv((object[])csvRow, paramterTypes);
//}
// ReadToEnd ??
while ((csvLine = streamReader.ReadToEnd()) != null)
{
if (Environment.NewLine != null)
{
var csvRow = csvLine.Split(',');
yield return ConvertCsv((object[])csvRow, paramterTypes); // System.ArgumentOutOfRangeException
}
}
}
}
private static object[] ConvertCsv(IReadOnlyList<object> cswRow, IReadOnlyList<Type> parameterTypes)
{
var convertedObject = new object[parameterTypes.Count];
for (int i = 0; i < parameterTypes.Count; i++)
{
convertedObject[i] = (parameterTypes[i] == typeof(int)) ? Convert.ToInt32(cswRow[i]) : cswRow[i]; // System.ArgumentOutOfRangeException
convertedObject[i] = (parameterTypes[i] == typeof(double)) ? Convert.ToDouble(cswRow[i]) : cswRow[i];
convertedObject[i] = (parameterTypes[i] == typeof(bool)) ? Convert.ToBoolean(cswRow[i]) : cswRow[i];
}
return convertedObject;
}
}
MyTestData.txt
1,2,true,
2,3,false,
3,10,true,
The first call to streamReader.ReadToEnd() will return the entire contents of the file in a string, not just one line. When you call csvLine.Split(',') you will get an array of 12 elements.
The second call to streamReader.ReadToEnd() will not return null as your while statement appears to expect, but an empty string. See the docu at
https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.readtoend?view=net-7.0
If the current position is at the end of the stream, returns an empty
string ("").
With the empty string, the call to call csvLine.Split(',') will return an array of length 0, which causes your exception when its first element (index 0) is accessed.
All of this could have been easily discovered by simply starting the test in a debugger.
It looks like you have some other issues here as well.
I don't understand what your if (Environment.NewLine != null) is intended to do, the NewLine property will never be null but should have one of the values "\r\n" or "\n" so the if will always be taken.
The parameters of your test method are arrays int[] and bool[], but you are checking against the types int, double and bool in your ConvertCsv method, so the alternative cswRow[i] will always be returned. You'll wind up passing strings to your method expecting int[] and bool[] and will at latest get an error there.
This method reads a data series from several rows and columns and returns it as an array for testing purposes.
The conversion of the columns can be adjusted according to existing pattern.
Thanks to Christopher!
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : Xunit.Sdk.DataAttribute
{
public CSVDataHandler(string pathCSV)
{
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
List<int> newLine = new();
List<int> GetInt = new();
List<bool> GetBool = new();
var reader = new StreamReader(pathCSV);
string readData = string.Empty;
while ((readData = reader.ReadLine()) != null)
{
string[] split = readData.Split(new char[] { ',' });
newLine.Add(int.Parse(split[0]));
GetInt.Add(int.Parse(split[1]));
GetBool.Add(bool.Parse(split[2]));
// Add more objects ...
}
yield return new object[] { newLine.ToArray(), GetInt.ToArray(), GetBool.ToArray() };
}
}

How to access a method (value) that is nested in a public static class

How do I access/get the string return values of a public static method that is nested in a public static class?
I want to display the string on a screen.
I've tried using private StringProperty variables to setDataString() the method return values as seen in the code snippet below.
The method named "byteToHex(buffer)" is the one whose return value I'm trying to access.
public static class SerialPortReader implements SerialPortEventListener
{
final public static char COMMA = ',';
final public static String COMMA_STR = ",";
final public static char ESCAPE_CHAR = '\\';
#Override
public void serialEvent(SerialPortEvent event)
{
if(event.isRXCHAR() && event.getEventValue() > 0)
{
try {
byte buffer[] = serialPort.readBytes();
byteToHex(buffer);
TransCeiveSerialData dataString = new TransCeiveSerialData();
dataString.setDataString(byteToHex(buffer));
/*
* wait some milliseconds before sending next data package to avoid data losses
*/
try {
Thread.sleep(100);
}catch(InterruptedException ie)
{
Logger.getLogger(TransCeiveSerialData.class.getName()).log(Level.SEVERE, null, ie);
}
}
catch(SerialPortException spe) {System.out.println("Error in port listener: " + spe);}
}
}
}
public static String byteToHex(byte x[])
{
StringBuffer retString = new StringBuffer();
for(int i = 0; i < x.length; ++i)
{
retString.append(Integer.toHexString(0x0100 + (x[i] & 0x00FF)).substring(1));
}
return retString.toString();
}
Using for exmaple System.out.println("Received data: " + instanceOfClass.getDataString()); in an external class to get the method's return string I get a "null". But I expect to get 31323334353637380d0a.
I've also tried binding the values but without any success.
Do you perhaps have any ideas how I can solve this problem? Your help will be very much appreciated.
Thanks a lot in advance!
AvJoe

Loop in string and get word between 2 character and save to list

we have string example :
www.example.com/default.aspx?code-1/price-2/code-4/
i want to get integers from code and price and save to list of integers.
for example , 1 and 4 are codes , 2 is price for filter in site.
InBetween = GetStringInBetween("Brand-", "/", Example, false, false);
please help me.
Below is a simple program that completes your requirement.
class Program
{
public void GetCodesAndPrice(string url,out List<int> listOfCodes, out List<int> listOfPrice )
{
listOfCodes=new List<int>();
listOfPrice = new List<int>();
url = url.Substring(url.IndexOf('?')+1);
var strArray = url.Split('/');
foreach (string s in strArray)
{
if(s.ToLower().Contains("code"))
listOfCodes.Add(GetIntValue(s));
else if(s.ToLower().Contains("price"))
listOfPrice.Add(GetIntValue(s));
}
// Now you have list of price in "listOfPrice" and codes in "listOfCodes",
// If you want to return these two list then declare as out
}
public int GetIntValue(string str)
{
try
{
return Convert.ToInt32(str.Substring(str.IndexOf('-') + 1));
}
catch (Exception ex)
{
// Handle your exception over here
}
return 0; // It depends on you what do you want to return if exception occurs in this function
}
public static void Main()
{
var prog = new Program();
List<int> listOfCodes;
List<int> listOfPrice;
prog.GetCodesAndPrice("www.example.com/default.aspx?code-1/price-2/code-4/", out listOfCodes,out listOfPrice);
Console.ReadKey();
}
}
It is complete console program. Test it and Embed in your program. Hope this will help you

programming logic problem

I need a function that can give me all possible combinations of a array back.
Example:
$source = array('a', 'b', 'c');
$target = thisiswhatisearch($source);
Now the $target should look like:
array('a','b','c','ab','ac','cb','abc')
I dont need the aa, bb, cc.
I also dont need the the ba, ca, acb.. because the order isn't important to me.
Thanks for any help.
Tried to be language agnostic but i guess its C like:
function combinations(array arr)
{
combos = array();
for (int i=1; i<2**arr.size(); i++)
{
int x = i;
int c = 0;
str = "";
while(x>0)
{
int rem = x % 2;
if(rem == 1)
str += arr[c];
x = x / 2;
c++;
}
combos.add(str);
}
return combos;
}
The Wikipedia entry for Combination has a link to C code that does this.
That's an out of the mind solution. It is probably not the fastest and cleanest one, but it kind of works. It's in Java, because I had it open:
public class Combination {
public static void main(String[] args) {
String[] source = {"a","b","c"};
List<String> result = combineMe(new ArrayList<String>(Arrays.asList(source)));
for (String string : result) {
System.out.println(string);
}
}
public static List<String> combineMe(List<String> source) {
List<String> result = new ArrayList<String>();
if (source.size()==0) {
result.add("");
return result;
}else{
String tmp = source.remove(0);
source = combineMe(source);
for (String string : source) {
result.add(("" + string).trim());
result.add(tmp + string);
}
}
return result;
}
}
The first entry in the resulting list is a fake one, and needs to be removed at the end

How can I get parameters values from a lamba expression for my nifty cache extension?

First of all it might be worth looking at this question:
How can I cache objects in ASP.NET MVC?
There some pseudo code that almost does what i want:
public class CacheExtensions
{
public static T GetOrStore<T>(this Cache cache, string key, Func<T> generator)
{
var result = cache[key];
if(result == null)
{
result = generator();
cache[key] = result;
}
return (T)result;
}
}
However, what I'd really like to do, is auto-generate the "key" from the generator. I figure i need to change the method signature to:
public static T GetOrStore<T>(this Cache cache,
System.Linq.Expressions.Expression<Func<T>> generator)
I want to use the method name, but also any parameters and their values to generate the key. I can get the method body from the expression, and the paramter names (sort of), but I have no idea how to get the paramter values...?
Or am I going about this the wrong way? Any ideas much appreciated.
Here's how I did it:
public static class ICacheExtensions
{
public static T GetOrAdd<T>(this ICache cache, Expression<Func<T>> getterExp)
{
var key = BuildCacheKey<T>(getterExp);
return cache.GetOrAdd(key, () => getterExp.Compile().Invoke());
}
private static string BuildCacheKey<T>(Expression<Func<T>> getterExp)
{
var body = getterExp.Body;
var methodCall = body as MethodCallExpression;
if (methodCall == null)
{
throw new NotSupportedException("The getterExp must be a MethodCallExpression");
}
var typeName = methodCall.Method.DeclaringType.FullName;
var methodName = methodCall.Method.Name;
var arguments = methodCall.Arguments
.Select(a => ExpressionHelper.Evaluate(a))
.ToArray();
return String.Format("{0}_{1}_{2}",
typeName,
methodName,
String.Join("|", arguments));
}
}
with this helper to evaluate nodes of an expression tree:
internal static class ExpressionHelper
{
public static object Evaluate(Expression e)
{
Type type = e.Type;
if (e.NodeType == ExpressionType.Convert)
{
var u = (UnaryExpression)e;
if (TypeHelper.GetNonNullableType(u.Operand.Type) == TypeHelper.GetNonNullableType(type))
{
e = ((UnaryExpression)e).Operand;
}
}
if (e.NodeType == ExpressionType.Constant)
{
if (e.Type == type)
{
return ((ConstantExpression)e).Value;
}
else if (TypeHelper.GetNonNullableType(e.Type) == TypeHelper.GetNonNullableType(type))
{
return ((ConstantExpression)e).Value;
}
}
var me = e as MemberExpression;
if (me != null)
{
var ce = me.Expression as ConstantExpression;
if (ce != null)
{
return me.Member.GetValue(ce.Value);
}
}
if (type.IsValueType)
{
e = Expression.Convert(e, typeof(object));
}
Expression<Func<object>> lambda = Expression.Lambda<Func<object>>(e);
Func<object> fn = lambda.Compile();
return fn();
}
}
When calling a function that produces a collection i want to cache i pass all my function's parameters and function name to the cache function which creates a key from it.
All my classes implement an interface that has and ID field so i can use it in my cache keys.
I'm sure there's a nicer way but somehow i gotta sleep at times too.
I also pass 1 or more keywords that i can use to invalidate related collections.

Categories

Resources