Difficulty with Deserialize method in class srialize - c#

I wrote a program that does work with files like delete and update, store, and search And all customers But I have a Problem with Deserialize method in class srialize.
I keep getting the following error:
Object of type 'System.String' cannot be converted to type 'System.Int32'
Project File
Video
public T Deserialize<T>(string entity)
{
var obj = Activator.CreateInstance<T>();
var stringProps = entity.Split(',');
var objProps = obj.GetType().GetProperties();
var propIndex = 0;
for (int i = 0; i < stringProps.Length; i++)
{
if (objProps[propIndex].PropertyType.FullName == "System.String")
{
objProps[propIndex].SetValue(obj, stringProps[i], null);
}
else if (objProps[propIndex].PropertyType.FullName == "System.Int32")
{
objProps[propIndex].SetValue(obj, stringProps[i], null);
}
else if (objProps[propIndex].PropertyType.FullName == "System.DateTime")
{
var cultureInfo = new CultureInfo("fa-IR");
DateTime dateTime = Convert.ToDateTime(stringProps[i], cultureInfo);
objProps[propIndex].SetValue(obj, stringProps[i], null);
}
else
{
i--;
}
propIndex++;
}
return obj;
}

You still have to convert the data type when you are setting it via reflection, modify your code to include the conversion as I have done below
public T Deserialize<T>(string entity)
{
var obj = Activator.CreateInstance<T>();
var stringProps = entity.Split(',');
var objProps = obj.GetType().GetProperties();
var propIndex = 0;
for (int i = 0; i < stringProps.Length; i++)
{
if (objProps[propIndex].PropertyType.FullName == "System.String")
{
objProps[propIndex].SetValue(obj, stringProps[i], null);
}
else if (objProps[propIndex].PropertyType.FullName == "System.Int32")
{
objProps[propIndex].SetValue(obj, Convert.ToInt32(stringProps[i]), null);
}
else if (objProps[propIndex].PropertyType.FullName == "System.DateTime")
{
var cultureInfo = new CultureInfo("fa-IR");
DateTime dateTime = Convert.ToDateTime(stringProps[i], cultureInfo);
objProps[propIndex].SetValue(obj, stringProps[i], null);
}
else
{
i--;
}
propIndex++;
}
return obj;
}

Related

System.Text.Json to Newtonsoft Json

Is there a JsonElement and JsonValueKind equivalent in newtonsoft Json? What would be the correct code to port the below code that uses System.Text.Json to newtonsoft Json? Reason for my port in due to my dll not able to find the right System.Buffers assembly version. I followed all the advices I could get but still I am unable to resolve it. So thought of using Newtonsoft Json.
public static Dictionary<string, dynamic> JsonDeserialize(string Json)
{
JsonElement elm = JsonSerializer.Deserialize<JsonElement>(Json);
Dictionary<string, dynamic> dict = ElementToDict(elm);
return dict;
}
public static dynamic ElementToDict(JsonElement obj)
{
if (obj.ValueKind == JsonValueKind.Number)
{
return StringToDecimal(obj.GetRawText());
}
else if (obj.ValueKind == JsonValueKind.String)
{
return obj.GetString();
}
else if (obj.ValueKind == JsonValueKind.True || obj.ValueKind == JsonValueKind.False)
{
return obj.GetBoolean();
}
else if (obj.ValueKind == JsonValueKind.Object)
{
var map = obj.EnumerateObject().ToList();
var newMap = new Dictionary<String, dynamic>();
for (int i = 0; i < map.Count; i++)
{
newMap.Add(map[i].Name, ElementToDict(map[i].Value));
}
return newMap;
}
else if (obj.ValueKind == JsonValueKind.Array)
{
var items = obj.EnumerateArray().ToList();
var newItems = new ArrayList();
for (int i = 0; i < items.Count; i++)
{
newItems.Add(ElementToDict(obj[i]));
}
return newItems;
}
else
{
return null;
}
}
You can try using JToken and JTokenType:
var tok = JsonConvert.DeserializeObject<JToken>("{\"test\": 1}"); // or JToken.Parse
Console.WriteLine(tok.Type); // prints "Object"
Thanks to #guru-stron I sucessfully ported to Newtonsoft.Json. Following is my code:
public static Dictionary<string, dynamic> JsonDeserialize(string Json)
{
Console.WriteLine(Json);
var elm = JsonConvert.DeserializeObject<JToken>(Json);
// Replace double with decimal in the map
Dictionary<string, dynamic> dict = ElementToDict(elm);
return dict;
}
public static dynamic ElementToDict(JToken obj)
{
if (obj.Type == JTokenType.Float || obj.Type == JTokenType.Integer)
{
return StringToDecimal(obj.ToString());
}
else if (obj.Type == JTokenType.String)
{
return obj.ToString();
}
else if (obj.Type == JTokenType.Boolean)
{
return obj.ToObject<Boolean>();
}
else if (obj.Type == JTokenType.Object)
{
var map = obj.Children().ToList();
var newMap = new Dictionary<String, dynamic>();
foreach (JProperty m in map)
{
newMap.Add(m.Name, ElementToDict(m.Value));
}
return newMap;
}
else if (obj.Type == JTokenType.Array)
{
var items = obj.AsJEnumerable().ToList();
var newItems = new ArrayList();
for (int i = 0; i < items.Count; i++)
{
newItems.Add(ElementToDict(obj[i]));
}
return newItems;
}
else
{
return null;
}
}

get members value, name and custom name from enum type with its name

i want to get a string from user and show him a list of enums member and its value.
for example i have this enum
public enum exampleEnum
{
[MyCustomProperty(customName = "نام1")]
member1 = 1,
[MyCustomProperty(customName = "نام2")]
member2 = 2,
}
help me for create this function
public List<enumResult> GetEnumDetailWithName(string enumName)
{
???
return result;// {name:'member1',value:1,customName='نام1'},{name:'member2',value:2,customName='نام2'}
}
i have write this code but not complete
in this lines get enum from all assembly and its done
then get all members of enum currectly
then for any member of enum add a member to result list , filling name is true but i cant fill Value and CustomName Field ...
public List<enumDetail> GetEnumDetailWithName(string enumName)
{
var enumFullName = $"Bamdad.PublicEnum.Enums+{enumName}";
var assemblyList = AppDomain.CurrentDomain.GetAssemblies();
Type type = null;
foreach (var assembly in assemblyList)
{
type = assembly.GetType(enumFullName);
if (type == null)
continue;
if (type.IsEnum)
break;
}
if (type == null)
return null;
//until this line get enum currectly
var members = type.GetMembers(BindingFlags.Public | BindingFlags.Static).Where(q=> q?.DeclaringType?.Name == enumName).ToList();
var properties = type.GetProperties();
if (!members.Any()) return null;
var result = new List<enumDetail>();
//get members currectly
foreach (var mem in members)
{
var resultItem = new enumDetail()
{
Name = mem.Name, // true
Value = 0, // i cant get
CustomName = "???" // i cant get
};
result.Add(resultItem);
}
return result;
}
please help me
for this question i should use Enum.GetValues and Enum.GetName , for getting custom attribute write a function and use it
public List<enumDetail> GetEnumMemberFromString(string enumName)
{
var enumFullName = $"Bamdad.PublicEnum.Enums+{enumName}";
var assemblyList = AppDomain.CurrentDomain.GetAssemblies();
Type type = null;
foreach (var assembly in assemblyList)
{
type = assembly.GetType(enumFullName);
if (type == null)
continue;
if (type.IsEnum)
break;
}
if (type == null) return null;
var valuesToNames = Enum.GetValues(type)
.Cast<object>()
.ToDictionary(q => Enum.GetName(type, q),q=> (int)q);
var result = valuesToNames.Select(q => new enumDetail()
{
Name = q.Key,
Value = q.Value,
CustomName = type.GetMyCustomProperty(q.Key)?.ToString() ?? q.Key
}).ToList();
return result;
}
this function is for getting custom attribute
public static object GetMyCustomProperty(this Type type,string member = "")
{
if (type == null)
return "";
MemberInfo[] memInfo = type.GetMember(member);
if (memInfo.Length <= 0) return member;
object[] attrs = memInfo[0].GetCustomAttributes(typeof(MyCustomPropertyAttribute), false);
if (!attrs.Any())
return null;
var result = ((MyCustomPropertyAttribute)attrs[0]);
return result.customName;
}

get the value of the attributes in C#

this is a very simple question.
such as this code:
if(o == null)
{
o = new { };
}
PropertyInfo[] p1 = o.GetType().GetProperties();
foreach(PropertyInfo pi in p1)
{}
but like this:
ModelA.ModelB.ModelC.ModelD.ModelE
how to get ModelE's value by reflect ModelA
There is a solution explained here:
using a helper method:
public static class ReflectionHelper
{
public static Object GetPropValue(this Object obj, String propName)
{
string[] nameParts = propName.Split('.');
if (nameParts.Length == 1)
{
return obj.GetType().GetProperty(propName).GetValue(obj, null);
}
foreach (String part in nameParts)
{
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
}
then the method can be used like this:
ModelA obj = new ModelA { */....*/ };
obj.GetPropValue("modelB.modelC.modelD.modelE");
please note that you should pass the property names to the function not the class names.
using nested function to do it like following:
var testObj = new
{
nameA = "A",
ModelB = new
{
nameB = "B",
ModelC = new
{
NameC = "C",
}
}
};
var result = ParseProperty(testObj, null, "ModelA");
public Dictionary<string, object> ParseProperty(object o, Dictionary<string, object> result, string preFix = null)
{
result = result ?? new Dictionary<string, object>();
if (o == null) return result;
Type t = o.GetType();
//primitive type or value type or string or nested return
if (t.IsPrimitive || t.IsValueType || t.FullName == "System.String" || t.IsNested) return result;
var proerties = o.GetType().GetProperties();
foreach (var property in proerties)
{
var value = property.GetValue(o);
result.Add($"{preFix}.{property.Name}", value);
//nested call
ParseProperty(value, result, $"{preFix}.{property.Name}");
}
return result;
}
I assume these are all anonymous types because otherwise you could just do GetProperties() on the type of ModelE.
So you basically have to next 5 of your loops like
foreach (PropertyInfo pi1 in o1.GetType().GetProperties())
{
if (pi.Name = "ModelB") // or some other criterion
{
o2 = pi1.GetValue(o1);
foreach (PropertyInfo pi2 in o2.GetType().GetProperties())
{
if (pi.Name = "ModelC") // or some other criterion
{
o3 = pi1.GetValue(o2);
// and so on
}
}
}
}

How to unflatten flattened json in C#

from this Answer I learned how to flatten a JSON object in c#.
from JSON String:
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
To:
The following are lines of strings, not an object
menu.id:file
menu.value:File
menu.popup.menuitem[0].value:New
menu.popup.menuitem[0].onclick:CreateNewDoc()
menu.popup.menuitem[1].value:Open
menu.popup.menuitem[1].onclick:OpenDoc()
menu.popup.menuitem[2].value:Close
menu.popup.menuitem[2].onclick:CloseDoc()
Now, i want to reverse the process.
I can found implementations from this question but it is in JavaScript.
How do I unflatten (return structured JSON from lines) it in C# with json.net?
I managed to solve it out.
Below is my code combined with Sarath Rachuri's flattening code.
I did not test it in too many cases, so it could be buggy.
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace JSONHelper
{
class JSONFlattener
{
private enum JSONType{
OBJECT, ARRAY
}
public static Dictionary<string, string> Flatten(JObject jsonObject)
{
IEnumerable<JToken> jTokens = jsonObject.Descendants().Where(p => p.Count() == 0);
Dictionary<string, string> results = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) =>
{
properties.Add(jToken.Path, jToken.ToString());
return properties;
});
return results;
}
public static JObject Unflatten(IDictionary<string, string> keyValues)
{
JContainer result = null;
JsonMergeSettings setting = new JsonMergeSettings();
setting.MergeArrayHandling = MergeArrayHandling.Merge;
foreach (var pathValue in keyValues)
{
if (result == null)
{
result = UnflatenSingle(pathValue);
}
else
{
result.Merge(UnflatenSingle(pathValue), setting);
}
}
return result as JObject;
}
private static JContainer UnflatenSingle(KeyValuePair<string, string> keyValue)
{
string path = keyValue.Key;
string value = keyValue.Value;
var pathSegments = SplitPath(path);
JContainer lastItem = null;
//build from leaf to root
foreach (var pathSegment in pathSegments.Reverse())
{
var type = GetJSONType(pathSegment);
switch (type)
{
case JSONType.OBJECT:
var obj = new JObject();
if (null == lastItem)
{
obj.Add(pathSegment,value);
}
else
{
obj.Add(pathSegment,lastItem);
}
lastItem = obj;
break;
case JSONType.ARRAY:
var array = new JArray();
int index = GetArrayIndex(pathSegment);
array = FillEmpty(array, index);
if (lastItem == null)
{
array[index] = value;
}
else
{
array[index] = lastItem;
}
lastItem = array;
break;
}
}
return lastItem;
}
public static IList<string> SplitPath(string path){
IList<string> result = new List<string>();
Regex reg = new Regex(#"(?!\.)([^. ^\[\]]+)|(?!\[)(\d+)(?=\])");
foreach (Match match in reg.Matches(path))
{
result.Add(match.Value);
}
return result;
}
private static JArray FillEmpty(JArray array, int index)
{
for (int i = 0; i <= index; i++)
{
array.Add(null);
}
return array;
}
private static JSONType GetJSONType(string pathSegment)
{
int x;
return int.TryParse(pathSegment, out x) ? JSONType.ARRAY : JSONType.OBJECT;
}
private static int GetArrayIndex(string pathSegment)
{
int result;
if (int.TryParse(pathSegment, out result))
{
return result;
}
throw new Exception("Unable to parse array index: " + pathSegment);
}
}
}
Purely System.Text.Json solution for unflatteing JSON. Requires .Net 6.
private static JsonNode Unflatten(Dictionary<string, JsonValue> source)
{
var regex = new System.Text.RegularExpressions.Regex(#"(?!\.)([^. ^\[\]]+)|(?!\[)(\d+)(?=\])");
JsonNode node = JsonNode.Parse("{}");
foreach (var keyValue in source)
{
var pathSegments = regex.Matches(keyValue.Key).Select(m => m.Value).ToArray();
for (int i = 0; i < pathSegments.Length; i++)
{
var currentSegmentType = GetSegmentKind(pathSegments[i]);
if (currentSegmentType == JsonValueKind.Object)
{
if (node[pathSegments[i]] == null)
{
if (pathSegments[i] == pathSegments[pathSegments.Length - 1])
{
node[pathSegments[i]] = keyValue.Value;
node = node.Root;
}
else
{
var nextSegmentType = GetSegmentKind(pathSegments[i + 1]);
if (nextSegmentType == JsonValueKind.Object)
{
node[pathSegments[i]] = JsonNode.Parse("{}");
}
else
{
node[pathSegments[i]] = JsonNode.Parse("[]");
}
node = node[pathSegments[i]];
}
}
else
{
node = node[pathSegments[i]];
}
}
else
{
if (!int.TryParse(pathSegments[i], out int index))
{
throw new Exception("Cannot parse index");
}
while (node.AsArray().Count - 1 < index)
{
node.AsArray().Add(null);
}
if (i == pathSegments.Length - 1)
{
node[index] = keyValue.Value;
node = node.Root;
}
else
{
if (node[index] == null)
{
var nextSegmentType = GetSegmentKind(pathSegments[i + 1]);
if (nextSegmentType == JsonValueKind.Object)
{
node[index] = JsonNode.Parse("{}");
}
else
{
node[index] = JsonNode.Parse("[]");
}
}
node = node[index];
}
}
}
}
return node;
}
private static JsonValueKind GetSegmentKind(string pathSegment) =>
int.TryParse(pathSegment, out _) ? JsonValueKind.Array : JsonValueKind.Object;
To flatten a JSON object:
arrayJSON.stringify()

Roslyn can't find IDictionary.Add interface implementation member

Why Roslyn in following example can't find IDictionary.Add interface member implementation in Dictionary type?
IDictionary.Add and Dictionary.Add correctly resolve by Roslyn, but then i can't find implementation IDictionary.Add method in Dictionary type.
Update
I added second code example with correct code.
VS2015, Roslyn 1.1.1:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;
namespace RoslynSymbolsTest
{
public class InterfaceMemberImplemnentationTest
{
public void Run()
{
string solutionPath = #"..\..\..\RoslynSymbolsTest.sln";
MSBuildWorkspace workspace = MSBuildWorkspace.Create();
Solution solution = workspace.OpenSolutionAsync(solutionPath).Result;
var project = solution.Projects.Where(p => p.Name == "RoslynSymbolsTest").Single();
var document = project.Documents.Where(d => d.Name == "InterfaceMemberImplemnentationTest.cs").Single();
var semanticModel = document.GetSemanticModelAsync().Result;
// IDictionary.Add
IMethodSymbol _idictionaryAddMethodSymbol = ResolveMethod(semanticModel, typeof(IDictionary<,>), "Add"); // ok
// Dictionary.Add
IMethodSymbol _dictionaryAddMethodSymbol = ResolveMethod(semanticModel, typeof(Dictionary<,>), "Add"); // ok
var implementationMethodSymbol = _dictionaryAddMethodSymbol.ContainingType.FindImplementationForInterfaceMember(_idictionaryAddMethodSymbol); // null
}
private ITypeSymbol ResolveType(SemanticModel semanticModel, Type type)
{
string[] names = type.FullName.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
INamespaceOrTypeSymbol scope = null;
for (int i = 0; i != names.Count(); ++i)
{
string metadataName = names[i];
string name = metadataName;
int index = name.IndexOf('`');
int numberOfGenericTypes = 0;
if (index != -1)
{
string sNumber = name.Substring(index + 1);
if (!int.TryParse(sNumber, out numberOfGenericTypes))
{
return null;
}
name = name.Substring(0, index);
}
IEnumerable<ISymbol> symbols = semanticModel.LookupNamespacesAndTypes(0, scope, name);
if (numberOfGenericTypes != 0)
{
symbols = symbols.Where(s => s.MetadataName == metadataName);
}
if (symbols.Count() == 1)
{
scope = (INamespaceOrTypeSymbol)symbols.First();
}
else
{
scope = null;
break;
}
}
return (ITypeSymbol)scope;
}
public IMethodSymbol ResolveMethod(SemanticModel semanticModel, Type type, string methodName)
{
ITypeSymbol typeSymbol = ResolveType(semanticModel, type);
if (typeSymbol == null)
{
return null;
}
var members = typeSymbol.GetMembers(methodName);
if (members.Length == 1
&& members[0] is IMethodSymbol)
{
return members[0] as IMethodSymbol;
}
return null;
}
}
}
Fixed Example:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;
namespace RoslynSymbolsTest
{
public class InterfaceMemberImplementationTest
{
class MyDisposable : IDisposable
{
public void Dispose() { }
}
public void Run()
{
string solutionPath = #"..\..\..\RoslynSymbolsTest.sln";
MSBuildWorkspace workspace = MSBuildWorkspace.Create();
Solution solution = workspace.OpenSolutionAsync(solutionPath).Result;
var project = solution.Projects.Where(p => p.Name == "RoslynSymbolsTest").Single();
var document = project.Documents.Where(d => d.Name == "InterfaceMemberImplementationTest.cs").Single();
var semanticModel = document.GetSemanticModelAsync().Result;
IMethodSymbol idictionaryAddMethodSymbol = ResolveMethod(semanticModel, typeof(IDictionary<,>), "Add");
IMethodSymbol idictionaryAddStringObjectMethodSymbol = ResolveMethod(semanticModel, typeof(IDictionary<,>), new Type[] { typeof(string), typeof(object) }, "Add");
IMethodSymbol idictionaryAddStringStringMethodSymbol = ResolveMethod(semanticModel, typeof(IDictionary<,>), new Type[] { typeof(string), typeof(string) }, "Add");
IMethodSymbol idictionaryGetItemMethodSymbol = ResolveMethod(semanticModel, typeof(IDictionary<,>), "get_Item");
IMethodSymbol dictionaryMethodSymbol = ResolveMethod(semanticModel, typeof(Dictionary<,>), "Add");
IMethodSymbol dictionaryStringObjectMethodSymbol = ResolveMethod(semanticModel, typeof(Dictionary<,>), new Type[] { typeof(string), typeof(object) }, "Add");
IMethodSymbol idisposableDisposeMethodSymbol = ResolveMethod(semanticModel, typeof(IDisposable), "Dispose");
IMethodSymbol myDisposableDisposeMethodSymbol = ResolveMethod(semanticModel, typeof(MyDisposable), "Dispose");
bool result1 = ImplementsInterfaceMember(dictionaryMethodSymbol, idictionaryAddMethodSymbol);
bool result2 = ImplementsInterfaceMember(dictionaryMethodSymbol, idictionaryGetItemMethodSymbol);
bool result3 = ImplementsInterfaceMember(dictionaryStringObjectMethodSymbol, idictionaryAddMethodSymbol);
bool result4 = ImplementsInterfaceMember(dictionaryStringObjectMethodSymbol, idictionaryGetItemMethodSymbol);
bool result5 = ImplementsInterfaceMember(dictionaryStringObjectMethodSymbol, idictionaryAddStringObjectMethodSymbol);
bool result6 = ImplementsInterfaceMember(dictionaryStringObjectMethodSymbol, idictionaryAddStringStringMethodSymbol);
bool result7 = ImplementsInterfaceMember(myDisposableDisposeMethodSymbol, idisposableDisposeMethodSymbol);
}
private static bool ImplementsInterfaceMember(IMethodSymbol implementationMethod, IMethodSymbol interfaceMethod)
{
if (!IsOpenMethod(interfaceMethod))
{
if (implementationMethod.Equals(implementationMethod.ContainingType.FindImplementationForInterfaceMember(interfaceMethod)))
{
return true;
}
}
else
{
INamedTypeSymbol interfaceTypeSymbol = interfaceMethod.ContainingType;
INamedTypeSymbol interfaceConstructedFromTypeSymbol = interfaceTypeSymbol.ConstructedFrom;
INamedTypeSymbol implementationTypeSymbol = implementationMethod.ContainingType;
var implementedInterfaces = implementationTypeSymbol.AllInterfaces.Where(i => i.ConstructedFrom.Equals(interfaceConstructedFromTypeSymbol));
foreach (var implementedInterface in implementedInterfaces)
{
foreach (var implementedInterfaceMember in implementedInterface.GetMembers(interfaceMethod.Name))
{
if (implementedInterfaceMember.OriginalDefinition.Equals(interfaceMethod))
{
var exactImplementedInterfaceMember = implementationMethod.ContainingType.FindImplementationForInterfaceMember(implementedInterfaceMember);
if (implementationMethod.Equals(exactImplementedInterfaceMember))
{
return true;
}
}
}
}
}
return false;
}
private static bool IsOpenMethod(IMethodSymbol method)
{
bool result = method.OriginalDefinition.Equals(method);
return result;
}
private ITypeSymbol ResolveType(SemanticModel semanticModel, Type type)
{
string[] names = type.FullName.Split(new[] { '.', '+' }, StringSplitOptions.RemoveEmptyEntries);
INamespaceOrTypeSymbol scope = null;
for (int i = 0; i != names.Count(); ++i)
{
string metadataName = names[i];
string name = metadataName;
int index = name.IndexOf('`');
int numberOfGenericTypes = 0;
if (index != -1)
{
string sNumber = name.Substring(index + 1);
if (!int.TryParse(sNumber, out numberOfGenericTypes))
{
return null;
}
name = name.Substring(0, index);
}
IEnumerable<ISymbol> symbols;
if (i == 0)
{
symbols = semanticModel.LookupNamespacesAndTypes(0, scope, name);
}
else
{
symbols = scope.GetMembers(name).Where(m => m.Kind == SymbolKind.Namespace || m.Kind == SymbolKind.NamedType);
}
if (numberOfGenericTypes != 0)
{
symbols = symbols.Where(s => s.MetadataName == metadataName);
}
if (symbols.Count() == 1)
{
scope = (INamespaceOrTypeSymbol)symbols.First();
}
else
{
scope = null;
break;
}
}
return (ITypeSymbol)scope;
}
private ITypeSymbol ResolveType(SemanticModel semanticModel, Type type, params Type[] typeParameters)
{
ITypeSymbol typeSymbol = ResolveType(semanticModel, type);
if (typeSymbol == null)
{
return null;
}
ITypeSymbol[] typeParametersSymbols = new ITypeSymbol[typeParameters.Length];
for (int i = 0; i != typeParameters.Length; ++i)
{
ITypeSymbol typeParameterSymbol = ResolveType(semanticModel, typeParameters[i]);
if (typeParameterSymbol == null)
{
return null;
}
typeParametersSymbols[i] = typeParameterSymbol;
}
INamedTypeSymbol constructedTypeSymbol = ((INamedTypeSymbol)typeSymbol).Construct(typeParametersSymbols);
return constructedTypeSymbol;
}
public IMethodSymbol ResolveMethod(SemanticModel semanticModel, Type type, string methodName)
{
ITypeSymbol typeSymbol = ResolveType(semanticModel, type);
if (typeSymbol == null)
{
return null;
}
var members = typeSymbol.GetMembers(methodName);
if (members.Length == 1
&& members[0] is IMethodSymbol)
{
return members[0] as IMethodSymbol;
}
return null;
}
public IMethodSymbol ResolveMethod(SemanticModel semanticModel, Type type, Type[] typeParameters, string methodName)
{
ITypeSymbol typeSymbol = ResolveType(semanticModel, type, typeParameters);
if (typeSymbol == null)
{
return null;
}
var members = typeSymbol.GetMembers(methodName);
if (members.Length == 1
&& members[0] is IMethodSymbol)
{
return members[0] as IMethodSymbol;
}
return null;
}
}
}
You aren't using generics enough.
IDictionary<,> is an unbound generic type. It is not a concrete type; instead, it can construct concrete types by filling in its generic parameters.
As such, it isn't an interface that can be implemented directly. For example, what if you have a class that implements it twice with two different sets of type parameters?
Instead, you need to call Construct() to build a concrete type with type parameters that match your implementing class.

Categories