Determine primitive types using roslyn - c#

Using Roslyn, how to determine whether an ITypeSymbol is a primitive type or not?
The ITypeSymbol does not have the IsPrimitive property like Type.IsPrimitive
Is there a way to convert ITypeSymbol to Type or some other way to determine whether an ITypeSymbol is a primitive type?

Looks like the code to determine that is in the TypedConstant class, but it is internal and I couldn't find a public API that would nicely get me there. I ended up copying the method into to my project.
/// <remarks>
/// TypedConstant isn't computing its own kind from the type symbol because it doesn't
/// have a way to recognize the well-known type System.Type.
/// </remarks>
internal static TypedConstantKind GetTypedConstantKind(ITypeSymbol type, Compilation compilation)
{
Debug.Assert(type != null);
switch (type.SpecialType)
{
case SpecialType.System_Boolean:
case SpecialType.System_SByte:
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
case SpecialType.System_Byte:
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_UInt64:
case SpecialType.System_Single:
case SpecialType.System_Double:
case SpecialType.System_Char:
case SpecialType.System_String:
case SpecialType.System_Object:
return TypedConstantKind.Primitive;
default:
switch (type.TypeKind)
{
case TypeKind.Array:
return TypedConstantKind.Array;
case TypeKind.Enum:
return TypedConstantKind.Enum;
case TypeKind.Error:
return TypedConstantKind.Error;
}
if (compilation != null &&
compilation.IsSystemTypeReference(type))
{
return TypedConstantKind.Type;
}
return TypedConstantKind.Error;
}
}

Whether a type is primitive or not depends on your language. In C# DateTime is not a primitive, but it is in VB. Since ITypeSymbol is used for both languages, it does not have language-specific properties.

Try the following extension methods:
//eg: symbol.IsFullNameEquals("List`1", "Generic", "Collections", "System")
internal static bool IsFullNameEquals(this ISymbol symbol, params string[] nameParts) {
if (symbol == null) throw new ArgumentNullException("symbol");
if (nameParts == null || nameParts.Length == 0) throw new ArgumentNullException("nameParts");
var idx = 0;
for (; symbol != null; symbol = symbol.ContainingSymbol) {
var name = symbol.MetadataName;
if (string.IsNullOrEmpty(name)) break;
if (idx == nameParts.Length) return false;
if (name != nameParts[idx]) return false;
idx++;
}
return idx == nameParts.Length;
}
//eg: var idx = symbol.MatchFullName(new []{"List`1", "Dictionary`2"}, new []{"Generic", "Collections", "System"});
//return value: -1: none; 0: symbol is List`1; 1: symbol is Dictionary`2
internal static int MatchFullName(this ISymbol symbol, string[] typeNames, string[] outerNameParts) {
if (symbol == null) throw new ArgumentNullException("symbol");
if (typeNames == null || typeNames.Length == 0) throw new ArgumentNullException("typeNames");
var fullLength = 1 + (outerNameParts != null ? outerNameParts.Length : 0);
int idx = 0, result = -1;
for (; symbol != null; symbol = symbol.ContainingSymbol) {
var name = symbol.MetadataName;
if (string.IsNullOrEmpty(name)) break;
if (idx == fullLength) return -1;
if (idx == 0) {
for (var i = 0; i < typeNames.Length; i++) {
if (name == typeNames[i]) {
result = i;
break;
}
}
if (result == -1) return -1;
}
else {
if (name != outerNameParts[idx - 1]) return -1;
}
idx++;
}
if (idx == fullLength) return result;
return -1;
}

Related

What 's the best solution to find an element in a deepest binary tree

Recently I had an interview question about finding an element in a binary tree. I coded both recursive and iterative solutions with C# but the problem was that in test cases when we have a tree with 1000000 nodes and all of them are on the left side. The interviewer said to me that my solutions (recursive and iterative) didn't save memory RAM enough for this case and I don't understand how to improve my solution.
// recusive Mode
public Node Find(int v)
{
if(v == value)
{
return this;
}else if(v <value){
if (left == null) return null;
return left.Find(v);
}else{
if (right == null) return null;
return right.Find(v);
}
}
// iterative
public Node Find(int v)
{
Node current = this;
while(value != v && current != null)
{
if (v < current.value)
{
if (current.left == null){ current = null};
else{current = current.left};
}
else
{
if (current.right == null) { current = null};
else{current = current.right };
}
}
return current;
}
Your iterative solution has some bugs in it.
// iterative
public Node Find(int v)
{
Node current = this;
// Here you need to compare current.value instead of just value
// Also, to use short-circuiting you need to put null-check first
// otherwise you might access current.value while current is null
while(current != null && current.value != v)
{
if (v < current.value)
{
//if (current.left == null){ current = null};
//else{current = current.left};
current = current.left; // the same as two commented out lines
}
else
{
//if (current.right == null) { current = null};
//else{current = current.right };
current = current.right; // the same as two commented out lines
}
}
return current;
}

Find an identical function signature with different name

Given an object and an instance method, I want to get a method that has the exact same signature but with a different, known name. That includes parameter list, generic parameters, possibly attributes if they're a part of the signature. How can I do that?
I know GetMethod() exists but I couldn't figure out which overload covers all the different possible signature variations.
Something like this may work in some cases:
public static bool HasSameSignature(MethodInfo m1, MethodInfo m2)
{
if (m1.GetGenericArguments().Length != m2.GetGenericArguments().Length)
return false;
var args1 = m1.GetParameters();
var args2 = m2.GetParameters();
if (args1.Length != args2.Length)
return false;
for (var idx = 0; idx < args1.Length; idx++)
{
if (!AreEquivalentTypes(args1[idx].ParameterType, args2[idx].ParameterType))
return false;
}
return true;
}
static bool AreEquivalentTypes(Type t1, Type t2)
{
if (t1 == null || t2 == null)
return false;
if (t1 == t2)
return true;
if (t1.DeclaringMethod != null && t2.DeclaringMethod != null && t1.GenericParameterPosition == t2.GenericParameterPosition)
return true;
if (AreEquivalentTypes(t1.GetElementType(), t2.GetElementType()))
return true;
if (t1.IsGenericType && t2.IsGenericType && t1.GetGenericTypeDefinition() == t2.GetGenericTypeDefinition())
{
var ta1 = t1.GenericTypeArguments;
var ta2 = t2.GenericTypeArguments;
for (var idx = 0; idx < ta1.Length; idx++)
{
if (!AreEquivalentTypes(ta1[idx], ta2[idx]))
return false;
}
return true;
}
return false;
}
So given your one method, you can do .GetMethods() on the type in question, and find the one whose name is correct, and for which HasSameSignature(...) on it and your one given method is true.
Type givenType = ...;
MethodInfo givenMethod = ...;
string givenDifferentName = ...;
var answer = givenType.GetMethods()
.SingleOrDefault(m => m.Name == givenDifferentName && HasSameSignature(m, givenMethod));

Serialize arithmetic expression-tree

I'm doing a simple task for investigation purposes. The problem is as follows:
Create an arithmetic expression with variables.
Build an AST for the expression.
Send it to the server (using Sockets)
Calculate an result of the server side and return the results.
Now I can to build a tree. This method doing it:
private readonly Stack<Expression> expressionStack = new Stack<Expression>();
private readonly Stack<Symbol> operatorStack = new Stack<Symbol>();
private readonly List<string> parameters = new List<string>();
public Expression<Func<decimal[], decimal>> Parse(string expression)
{
if (string.IsNullOrWhiteSpace(expression))
{
return s => 0;
}
var arrayParameter = Expression.Parameter(typeof(decimal[]), "args");
parameters.Clear();
operatorStack.Clear();
expressionStack.Clear();
using (var reader = new StringReader(expression))
{
int peek;
while ((peek = reader.Peek()) > -1)
{
var next = (char)peek;
if (char.IsDigit(next))
{
expressionStack.Push(ReadOperand(reader));
continue;
}
if (char.IsLetter(next))
{
expressionStack.Push(ReadParameter(reader, arrayParameter));
continue;
}
if (Operation.IsDefined(next))
{
if (next == '-' && expressionStack.Count == 0)
{
reader.Read();
operatorStack.Push(Operation.UnaryMinus);
continue;
}
var currentOperation = ReadOperation(reader);
EvaluateWhile(() => operatorStack.Count > 0 && operatorStack.Peek() != Parentheses.Left &&
currentOperation.Precedence <= ((Operation)operatorStack.Peek()).Precedence);
operatorStack.Push(currentOperation);
continue;
}
if (next == '(')
{
reader.Read();
operatorStack.Push(Parentheses.Left);
if (reader.Peek() == '-')
{
reader.Read();
operatorStack.Push(Operation.UnaryMinus);
}
continue;
}
if (next == ')')
{
reader.Read();
EvaluateWhile(() => operatorStack.Count > 0 && operatorStack.Peek() != Parentheses.Left);
operatorStack.Pop();
continue;
}
if (next == ' ')
{
reader.Read();
}
else
{
throw new ArgumentException(string.Format("Encountered invalid character {0}", next),
"expression");
}
}
}
EvaluateWhile(() => operatorStack.Count > 0);
return Expression.Lambda<Func<decimal[], decimal>>(expressionStack.Pop(), arrayParameter);
}
This method works, and returns the expected result.
Before being sent to the server I want to serialize a tree to binary type. My question is as follows. Which is the simplest way I can apply for this?
I found a lot of solutions for LINQ serialization, but they are too big. I don't need the full functionality of these solutions. In addition, usually, they provide the JSON or XML-serialization, but I need a binary serialization.
Can somebody suggest a simple and easy solution for this problem?

How to I convert from Type.FullName to a C# type name?

Examples,
"Namespace.ClassName+NestedClassName" becomes "Namespace.ClassName.NestedClassName".
"System.Collections.Generic.List`1[System.String]" becomes "System.Collections.Generic.List".
I need this for a code generator and I don't want to do a simple RegEx replace because of edge cases such as type names with '+' symbols in them. (Yes, though stupid that is possible.)
/// <summary>
/// Gets the fully quantified name in C# format.
/// </summary>
public string CSharpFullName
{
get
{
if (m_CSharpFullName == null)
{
var result = new StringBuilder(m_TypeInfo.ToString().Length);
BuildCSharpFullName(m_TypeInfo.AsType(), null, result);
m_CSharpFullName = result.ToString();
}
return m_CSharpFullName;
}
}
static void BuildCSharpFullName(Type typeInfo, List<Type> typeArgs, StringBuilder result)
{
var localTypeParamCount = typeInfo.GetTypeInfo().GenericTypeParameters.Length;
var localTypeArgCount = typeInfo.GetTypeInfo().GenericTypeArguments.Length;
var typeParamCount = Math.Max(localTypeParamCount, localTypeArgCount);
if (typeArgs == null)
typeArgs = new List<Type>(typeInfo.GetTypeInfo().GenericTypeArguments);
if (typeInfo.IsNested)
{
BuildCSharpFullName(typeInfo.DeclaringType, typeArgs, result);
}
else
{
result.Append(typeInfo.Namespace);
}
result.Append(".");
foreach (var c in typeInfo.Name)
{
if (c == '`') //we found a generic
break;
result.Append(c);
}
if (localTypeParamCount > 0)
{
result.Append("<");
for (int i = 0; i < localTypeParamCount; i++)
{
if (i > 0)
result.Append(",");
BuildCSharpFullName(typeArgs[i], null, result); //note that we are "eating" the typeArgs that we passed to us from the nested type.
}
typeArgs.RemoveRange(0, localTypeParamCount); //remove the used args
result.Append(">");
}
else if (localTypeArgCount > 0 && typeArgs.Count > 0)
{
result.Append("<");
for (int i = 0; i < Math.Min(localTypeArgCount, typeArgs.Count); i++)
{
if (i > 0)
result.Append(",");
BuildCSharpFullName(typeArgs[i], null, result);
}
result.Append(">");
}
}
You could use Type.GetType to parse the string into a Type object. From there you could use GetGenericArguments and other members to get the Type info of the individual components. You could use those to reconstruct your target string.

Converting string expression to boolean logic - C#

I want to convert a string expression to a real boolean expression.
The expression below will be an input (string):
"(!A && B && C) || (A && !B && C) || (A && B && !C) || (A && B && C)"
The variables A, B and C will have your boolean values (true or false).
How I can transforming a string expression, replace the logic values and validate using C#?
If you don't want to use some available libraries to parse that string you need to separate those characters and implement the logic based on comparison. So for example say we have "a || b", we can loop though each character and decide the appropriate operation based on char == '|'. For more complex situation I'd use a stack to keep track of each results, like this one that can handle && and || without parentheses:
public bool ConvertToBool(string op, bool a, bool b)
{
var st = new Stack<bool>();
var opArray = op.ToCharArray();
var orFlag = false;
var andFlag = false;
for (var i = 0; i < opArray.Length; i++)
{
bool top;
switch (opArray[i])
{
case '|':
i++;
orFlag = true;
break;
case '&':
i++;
andFlag = true;
break;
case 'a':
if (orFlag)
{
top = st.Pop();
st.Push(top || a);
orFlag = false;
}
else if (andFlag)
{
top = st.Pop();
st.Push(top && a);
andFlag = false;
continue;
}
st.Push(a);
break;
case 'b':
if (orFlag)
{
top = st.Pop();
st.Push(top && b);
orFlag = false;
}
else if (andFlag)
{
top = st.Pop();
st.Push(top && b);
andFlag = false;
continue;
}
st.Push(b);
break;
}
}
return st.Pop();
}

Categories

Resources