I am trying to find an object in my database that meets two conditions, I did a search on stackoverflow and found this one which looks exactly like what I need. However, I have this code:
if (db.MinimumProductInfo.Find(pc => pc.ItemCode == productInfoWithNote.ItemCode && pc.Region == productInfoWithNote.Region))
and I am receiving this error:
Cannot Convert Lambda Expression to type 'object[]' because it is not
a delegate type.
MinimumProductInfo is my class and productInfoWithNote is the viewmodel that I pass in to the method.
Try using FirstOrDefault which will return null if no object meets the conditions:
var myObject = db.MinimumProductInfo.FirstOrDefault(pc => pc.ItemCode ==
productInfoWithNote.ItemCode && pc.Region == productInfoWithNote.Region);
if(myObject != null)
{
// use your object here
}
NOTE: Find method returns the first match element if exists and if not it will return the default value of element's type and you are using it like it will return a boolean value.
Related
I'm currently trying to find invocations of .ExecuteSqlCommand and examine the first value being passed to the sql param.
Here is an example of the differences I've found in our code base.
ExecuteSqlCommand("[sql statement here]");
vs.
var sql = "sql statement";
ExecuteSqlCommand(sql);
So far, I have this:
var invocations = root.DescendantNodes()
.OfType<InvocationExpressionSyntax>()
.Select(ie => ModelExtensions.GetSymbolInfo(model, ie).Symbol)
.Where(symbol => symbol != null && symbol.Name == "ExecuteSqlCommand");
foreach (var invocation in invocations)
{
var method = (IMethodSymbol)invocation;
foreach (var param in method.Parameters)
{
//I can't quite seem to get information from IParameterSymbol about whether the param is a string literal, or a reference to a string via a variable.
}
}
If the param is not a string, and instead, a var, then I'll need to get the value of the var (as much as it's defined at runtime).
I'm not too sure if this is a job for the SemanticModel or the SyntaxTree, but my GUESS is that the SemanticModel should have the richer information I need to let me discover what I'm looking for.
My overall goal is to interrogate the sql being passed to the ExecuteSqlCommand method.
Thanks!
SemanticModel.GetConstantValue is the API we have for handling this situation.
It can accept both a syntax node and an expression. You will still need to track the state of variables back to their declaration sites and determine if they were given a constant expression.
I would use SemanticModel.GetSymbolInfo.Symbol?.DeclaringSyntaxReferences.First() to find the declaration site of a variable and then check to see if its a constant expression.
The Syntax API could be used to extract the sql statement value but depends on whether the variable declaration (i.e. var sql = "sql statement";) is included as part of code submitted to the syntax tree.
For example, if it's part of the same method implementation as where ExcuteSqlCommand() is called then you can first get the name of variable (i.e. sql) passed to it and use that to find the matching variable declaration statement within that same method. Finally, the sql statement value (i.e. "sql statement") can be extracted from that.
The following code first checks if the sql value is passed as a string literal otherwise looks for the variable declaration. The assumption it's all within the same method:
// whatever c# *method* code contains the sql.
// otherwise the root of the tree would need to be changed to filter to a specific single `MethodDeclarationSyntax`.
string submittedCode = "public void SomeMethodContainingSql(){ ...//rest of code...";
var tree = CSharpSyntaxTree.ParseText(submittedCode);
var root = (CompilationUnitSyntax) tree.GetRoot();
var arguments = root
.DescendantNodes()
.OfType<InvocationExpressionSyntax>()
.First(node => node.DescendantNodes().OfType<IdentifierNameSyntax>()
.First()
.Identifier.Text == "ExecuteSqlCommand")
.ArgumentList.DescendantNodes().ToList();
string sqlStatementValue = "";
var literalExpression = arguments.OfType<LiteralExpressionSyntax>().FirstOrDefault();
if (literalExpression != null)
{
sqlStatementValue = literalExpression.GetText().ToString();
}
else
{
var variableName = arguments
.First()
.ToFullString();
var variableDeclaration = root
.DescendantNodes()
.OfType<VariableDeclarationSyntax>()
.Single(node => node.DescendantNodes().OfType<VariableDeclaratorSyntax>()
.First()
.Identifier.Text == variableName);
sqlStatementValue = variableDeclaration.DescendantNodes()
.OfType<LiteralExpressionSyntax>()
.First()
.DescendantTokens()
.First()
.Text;
}
Otherwise, may need to look for the variable declaration in other parts of the submitted code (ex. class fields, properties, other methods, etc.) which is a bit more cumbersome.
Unfortunately Roslyn cannot provide a variable's value in a common cases when values is defined at runtime, because Roslyn actually doesn't know all possible values which may pass from outside the program, it doesn't calculate them and so on so forth. But if you can limit the needed cases to a inlining strings or variables which was declared and initialized at strings, Roslyn may help you with this:
You need to keep InvocationExpressionSyntax (or directly their first arguments)
var invocations = root.DescendantNodes()
.OfType<InvocationExpressionSyntax>()
.Select(ie => (ModelExtensions.GetSymbolInfo(model, ie).Symbol, ie))
// Would be better to compare not method's name but it FQN
.Where((symbol, node)) => symbol != null && symbol.Name == "ExecuteSqlCommand" &&
symbol.Parameters.Length == 1 &&
symbol.Parameters[0].Type.SpecialType == SpecialType.System_String &&
node.ArgumentList.Arguments.Count == 1)
.Select((symbol, node) => node);
You need to check not method parameter, but method argument which was passed to it
foreach (var invocation in invocations)
{
var argument = invocation .ArgumentList.Arguments[0];
if (argument is LiteralExpressionSyntax literal && literal.IsKind(SyntaxKind.StringLiteralExpression))
{
// You find invocation of kind `ExecuteSqlCommand("sql")`
}
else
{
var argSymbol = ModelExtensions.GetSymbolInfo(model, argument).Symbol;
if (!(argSymbol is null) && (argSymbol.Kind == SymbolKind.Field || argSymbol.Kind == SymbolKind.Property || argSymbol.Kind == SymbolKind.Local))
{
if (argSymbol.DeclaringSyntaxReferences.Length == 1)
{
var declarationNode = argSymbol.DeclaringSyntaxReferences[0].GetSyntax();
// I'm actually don't remember what exactlly `GetSyntax` returns for fields or locals:
// VariableDeclaratorSyntax or one of it parent LocalDeclarationStatementSyntax and FieldDeclarationSyntax, but if it returns declarations you also can
// get from them VariableDeclaratorSyntax that you need, it's just be a more deep pattern matching
if (declarationNode is VariableDeclaratorSyntax declaratorSyntax &&
declaratorSyntax.EqualsValueClauseSyntax?.Value is LiteralExpressionSyntax literal2 && literal2.IsKind(SyntaxKind.StringLiteralExpression) )
{
// You find invocation of kind `ExecuteSqlCommand(variable)` where variable is local variable or field
}
else if (declarationNode is PropertyDeclarationSyntax property)
{
// You can do the same things for properties initializer or expression body that you was do for fields and locals to check your case,
// but it doesn't work for property with get/set accessors in a common cases
}
}
}
}
}
I'm attempting to understand the syntax of a piece of code someone else wrote.
The method is returning a bool, and the return statement looks like this:
return user.UserStatus == Models.User.UserStatuses.Inactive && user.IsLocked;
UserStatuses is a enum.
So it appears to me it returns the property of object user called UserStatus, however UserStatus is an enum, not a bool, and then && adds the bool as user.IsLocked, where is a bool.
I can't seem to understand how this is legal in c#, since it appears to return two parameters.
Add some parenthesis, or separate your line into multiple statements, and it makes sense. The compiler is just doing it for you (more or less). Your statement is equivalent to:
return ((user.UserStatus == Models.User.UserStatuses.Inactive) && user.IsLocked);
or
bool inactive = user.UserStatus == Models.User.UserStatuses.Inactive;
bool inactiveAndLocked = inactive && user.isLocked;
return inactiveAndLocked;
The key here is that return is taking an expression (not a parameter) and using the result of that expression, which is just one "thing" as the C# spec dictates.
bool result = (user.UserStatus == Models.User.UserStatuses.Inactive) &&
user.IsLocked;
return result;
It is just returning a boolean condition. Hypothetically, you could also check that same code on a IF statement like:
if(user.UserStatus == Models.User.UserStatuses.Inactive && user.IsLocked)
UserStatus is an enum but the base type of an enum is int. This is compared to the specific enum type. So the first part is basically (int == int) which yields a bool. The bool is then conditionally and'ed with the IsLocked value (bool && bool) to yield the final result.
When I get deserialized XML result into xsd-generated tree of objects and want to use some deep object inside that tree a.b.c.d.e.f, it will give me exception if any node on that query path is missing.
if(a.b.c.d.e.f != null)
Console.Write("ok");
I want to avoid checking for null for each level like this:
if(a != null)
if(a.b != null)
if(a.b.c != null)
if(a.b.c.d != null)
if(a.b.c.d.e != null)
if(a.b.c.d.e.f != null)
Console.Write("ok");
First solution is to implement Get extension method that allows this:
if(a.Get(o=>o.b).Get(o=>o.c).Get(o=>o.d).Get(o=>o.e).Get(o=>o.f) != null)
Console.Write("ok");
Second solution is to implement Get(string) extension method and use reflection to get result looking like this:
if(a.Get("b.c.d.e.f") != null)
Console.Write("ok");
Third solution, could be to implement ExpandoObject and use dynamic type to get result looking like this:
dynamic da = new SafeExpando(a);
if(da.b.c.d.e.f != null)
Console.Write("ok");
But last 2 solutions do not give benefits of strong typing and IntelliSense.
I think the best could be fourth solution that can be implemented with Expression Trees:
if(Get(a.b.c.d.e.f) != null)
Console.Write("ok");
or
if(a.Get(a=>a.b.c.d.e.f) != null)
Console.Write("ok");
I already implemented 1st and 2nd solutions.
Here is how 1st solution looks like:
[DebuggerStepThrough]
public static To Get<From,To>(this From #this, Func<From,To> get)
{
var ret = default(To);
if(#this != null && !#this.Equals(default(From)))
ret = get(#this);
if(ret == null && typeof(To).IsArray)
ret = (To)Activator.CreateInstance(typeof(To), 0);
return ret;
}
How to implement 4th solution if possible ?
Also it would be interesting to see how to implement 3rd solution if possible.
So the starting place is creating an expression visitor. This lets us find all of the member accesses within a particular expression. This leaves us with the question of what to do for each member access.
So the first thing is to recursively visit on the expression that the member is being accessed on. From there, we can use Expression.Condition to create a conditional block that compares that processed underlying expression to null, and returns null if true an the original starting expression if it's not.
Note that we need to provide implementations for both Members and method calls, but the process for each is basically identical.
We'll also add in a check so that of the underlying expression is null (which is to say, there is no instance and it's a static member) or if it's a non-nullable type, that we just use the base behavior instead.
public class MemberNullPropogationVisitor : ExpressionVisitor
{
protected override Expression VisitMember(MemberExpression node)
{
if (node.Expression == null || !IsNullable(node.Expression.Type))
return base.VisitMember(node);
var expression = base.Visit(node.Expression);
var nullBaseExpression = Expression.Constant(null, expression.Type);
var test = Expression.Equal(expression, nullBaseExpression);
var memberAccess = Expression.MakeMemberAccess(expression, node.Member);
var nullMemberExpression = Expression.Constant(null, node.Type);
return Expression.Condition(test, nullMemberExpression, node);
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Object == null || !IsNullable(node.Object.Type))
return base.VisitMethodCall(node);
var expression = base.Visit(node.Object);
var nullBaseExpression = Expression.Constant(null, expression.Type);
var test = Expression.Equal(expression, nullBaseExpression);
var memberAccess = Expression.Call(expression, node.Method);
var nullMemberExpression = Expression.Constant(null, MakeNullable(node.Type));
return Expression.Condition(test, nullMemberExpression, node);
}
private static Type MakeNullable(Type type)
{
if (IsNullable(type))
return type;
return typeof(Nullable<>).MakeGenericType(type);
}
private static bool IsNullable(Type type)
{
if (type.IsClass)
return true;
return type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
}
We can then create an extension method to make calling it easier:
public static Expression PropogateNull(this Expression expression)
{
return new MemberNullPropogationVisitor().Visit(expression);
}
As well as one that accepts a lambda, rather than any expression, and can return a compiled delegate:
public static Func<T> PropogateNull<T>(this Expression<Func<T>> expression)
{
var defaultValue = Expression.Constant(default(T));
var body = expression.Body.PropogateNull();
if (body.Type != typeof(T))
body = Expression.Coalesce(body, defaultValue);
return Expression.Lambda<Func<T>>(body, expression.Parameters)
.Compile();
}
Note that, to support cases where the accessed member resolves to a non-nullable value, we're changing the type of those expressions to lift them to be nullable, using MakeNullable. This is a problem with this final expression, as it needs to be a Func<T>, and it won't match if T isn't also lifted. Thus, while it's very much non-ideal (ideally you'd never call this method with a non-nullable T, but there's no good way to support this in C#) we coalesce the final value using the default value for that type, if necessary.
(You can trivially modify this to accept a lambda accepting a parameter, and pass in a value, but you can just as easily close over that parameter instead, so I see no real reason to.)
It's also worth pointing out that in C# 6.0, when it's actually released, we'll have an actual null propogation operator (?.), making all of this very unnecessary. You'll be able to write:
if(a?.b?.c?.d?.e?.f != null)
Console.Write("ok");
and have exactly the semantics you're looking for.
I have a Type object. I want to find every object in a List that is of this type. Is there something like list.OfType<> using a Type object? Or do I have to use it this way:
list.Where(obj => obj.GetType() == type) // corrected thanks to jmcilhinney
This will be heavily used in my application, so I need to find a solution that is as fast as possible.
You need to call Where:
var items = myList.Where(item => item.GetType() == myType);
You can't use OfType<T> in the case where you have the type stored in a variable. Remember that, with generics, the type parameter is a compile-time constant. Therefore you can't use a generic function by specifying T in a variable, which is not known until runtime.
To look at this another way, there are two possible variants of your function:
public IEnumerable<T> GetOfType<T>(IEnumerable<object> list)
{
return list.OfType<T>();
}
public IEnumerable<object> GetOfType(IEnumerable<object> list, Type type)
{
return list.All(obj => obj != null && obj.GetType() == type);
}
To use the generic version, ultimately some consumer of the function is going to need to supply the type as a compile-time constant.
I have a method that takes as an input parameter an object of type IEnumerable. I want to enumerate the enumeration and for each item use reflection to get the value for each property.
I have the following code:
protected void WriteData(IEnumerable data)
{
var enumerationTypeInfo = data.GetType();
var itemTypeInfo = enumerationTypeInfo.GetElementType();
...
}
The problem is enumerationTypeInfo.GetElementType() always returns null. In particular, I'm passing in a List<Entry> into WriteData, where Entry is a class I created. When I use the debugger and set a breakpoint I can see that enumerationTypeInfo correctly shows that it's a List of type Entry, but why does GetElementType return null?
Thanks
GetElementType() returns the element type of arrays. List<T> is not an array type, and therefore has no "element type."
If you want to get the type of elements a random IEnumerable<T> produces, try something like this:
public static Type GetEnumerableType(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
return type.GetGenericArguments()[0];
var iface = (from i in type.GetInterfaces()
where i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)
select i).FirstOrDefault();
if (iface == null)
throw new ArgumentException("Does not represent an enumerable type.", "type");
return GetEnumerableType(iface);
}
Note that types can implement more than one version of the same generic interface; a type can implement both IEnumerable<int> and IEnumerable<string> for example. How you handle that case is up to you. The method I provide will take whichever interface type the runtime hands it first.
See an example using the above method on ideone.
GetElementType is for use with arrays, not other generic classes. To get a generic type's generic parameters, you can use Type.GetGenericArguments.