I want to have a class in a WPF app that can extract strings from a resx generated class without having to know the actual resx. other than by the params needed to instantitiate the ResourceManager and use GetString()
The test for the project structure shown fails however:
[Test]
public void CanGetString() {
var expected = MainWindow.MenuItem_Header_English; // value is "English"
var baseName = MainWindow.ResourceManager.BaseName;
var asm = typeof (MainWindow).Assembly;
var rm = new ResourceManager(baseName, asm);
var actual = rm.GetString("MenuItem_Header_English"); // returns null
Assert.That(expected, Is.EqualTo(actual));
}
Can someone confirm this should be possible and tell me what I am doing wrong? Is there a better way to read string values embedded resources?
Cheers,
Berryl
will this work for you
var rm = MainWindow.ResourceManager.GetString("MenuItem_Header_English")
var expected = MainWindow.MenuItem_Header_English;
// not sure how you are comparing String value to what looks like a type..
Related
I have been trying to write C# code to output the network tab contents of Developer tools as JSONArray, this is what I have so far:
*IWebDriver driver = new ChromeDriver(#"C:\Users\xxx\Downloads\chromedriver_win32");
driver.Navigate().GoToUrl("https://google.com");
String scriptToExecute = "var performance = window.performance || window.mozPerformance || window.msPerformance || window.webkitPerformance || {}; var network = performance.getEntries() || {}; return network;";
String netData = ((IJavaScriptExecutor)driver).ExecuteScript(scriptToExecute).ToString();
Console.WriteLine(netData);*
And the other:
*IWebDriver driver = new ChromeDriver(#"C:\Users\xxx\Downloads\chromedriver_win32");
driver.Navigate().GoToUrl("https://google.com");
String ste = "Return window.performance.getEntries();";
String Timings = ((IJavaScriptExecutor)driver).ExecuteScript(ste).ToString();
Console.WriteLine(Timings);*
But my output is not giving the expected result. It looks like the String netData variable is returning as empty, thinking it is an issue with the Script.
Any suggestions on a workaround for this?
You have to be aware of the return type of ExecuteScript method. If case of JS script
return window.performance.getEntries()
it will be
IReadOnlyCollection<object>
getEntries() returns an array of objects - in case of c# code it will be IDictionary<string, object> - key is a JS object property name, value is its value (:))
You have to do something like that:
var ste = "return window.performance.getEntries();";
var scriptResult = (IReadOnlyCollection<object>)(IJavaScriptExecutor)driver).ExecuteScript(ste);
var perfEntries = scriptResult.Select(e => ((IDictionary<string, object>)e);
//(result will be an IEnumerable of IDictionary<string,object>), you can create a new, custom class to convert dictionaries to more verbose objects)
PS
Please, try to stick to c# convention -> e.g. use string instead of String; name variable using lower case etc.
I am trying to read some .sql files that I have embedded in a resx file called SQLUpdateScripts. All my files in SQLupdateScripts.resx are in format 00001.sql,00002.sql,0003.sql etc.
I want to read the content of each sql file and execute it based on two variables
for (int i = DbVersion+1; i <= FileDbVersion; i++)
{
string updateScripts = "script_" + i.ToString("D5");
....
var sqlqueries = myString.Split(new[] { "\nGO", "\ngo" }, StringSplitOptions.RemoveEmptyEntries);
etc....
I tried many suggestions in stackoverflow but all of them are returning null or exception
ResourceManager sqLUpdateScripts = new ResourceManager(typeof(SQLUpdateScripts));
string myString = sqLUpdateScripts.GetString(updateScripts);
also
object[] args = new object[] { updateScripts };
SQLUpdateScripts obj = new SQLUpdateScripts();
obj.GetType().InvokeMember(updateScripts,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
Type.DefaultBinder, obj, args);
The code in SqlUpdateScripts.Designer.cs for every sql file is
internal static string script_00001
{
get {
return ResourceManager.GetString("script_00001", resourceCulture);
}
}
internal static string script_00002
{
get {
return ResourceManager.GetString("script_00002", resourceCulture);
}
}
I read that I must use reflection to call each file as method by using the invokeMember gives me Exception that cannot find class SqlUpdateScripts.script_0001'.
When I tried using the ResourceManager it just return myString as null.
If I called by hand:
var sqlqueries = SQLUpdateScript.script_0001.Split(new[] { "\nGO", "\ngo" }, StringSplitOptions.RemoveEmptyEntries);
it works fine but I want to use variables for the filename and not a standard filename
I found the problem.
It was a dump error I made. I gave wrong values while testing in DBVersion and fileDBVersion so when I used
for (int i = DbVersion+1; i <= FileDbVersion; i++)
instead of giving me value script_00001 it gave me the value script_01001
So now that it is working I found that you can call files as strings in resx files with two ways
First:
ResourceManager sqLUpdateScripts = new ResourceManager(typeof(SQLUpdateScripts));
string myString = sqLUpdateScripts.GetString(updateScripts);
Second way:
string resVal = SQLUpdateScripts.ResourceManager.GetString(updateScripts, Thread.CurrentThread.CurrentCulture);
GetString in second way has two overloads, one is with out CultureInfo and one is with specify the CultureInfo in case you want to call another language for example.
I don't know if there is a way to avoid future mistakes while calling wrong resx resource , maybe if there is a way to enumerate all the resources and then just choose one.
If I find a way I will add it here.
I am trying to create a code analyzer in Roslyn, and I need to analyze SqlCommand usage in a project. I have written the analyzer and it works fine when I test it out in Visual Studio project, but when I am writing unit test and I am trying to get SymbolInfo from SemanticModel and am always getting null.
What am i missing?
string test = #"public class TestClass
{
public void SomeMethod(int x)
{
var command = new SqlCommand(""Some COmmabnd"",new SqlConnection(""conn string""));
command.ExecuteReader();
}
}";
var tree = CSharpSyntaxTree.ParseText(test);
var systemDataReference = MetadataReference.CreateFromFile(typeof(System.Data.IDbCommand).Assembly.Location);
var systemConfigurationReference = MetadataReference.CreateFromFile(typeof(ConfigurationManager).Assembly.Location);
var systemTransactionReference = MetadataReference.CreateFromFile(typeof(Transaction).Assembly.Location);
var systemXmlnReference = MetadataReference.CreateFromFile(typeof(XPathDocument).Assembly.Location);
var system = MetadataReference.CreateFromFile(typeof(Uri).Assembly.Location);
var mscorRef = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var systemCore = MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location);
var systemNumerics = MetadataReference.CreateFromFile(typeof(BigInteger).Assembly.Location);
var compilation = CSharpCompilation.Create("TestCompilatin", new[] {tree},
new[]
{
mscorRef, system, systemXmlnReference, systemTransactionReference, systemDataReference,
systemConfigurationReference,systemCore,systemNumerics
});
var semanticModel = compilation.GetSemanticModel(tree);
var invocationExpressions = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>();
foreach (var invocationExpressionSyntax in invocationExpressions)
{
var memeber = invocationExpressionSyntax.Expression as MemberAccessExpressionSyntax;
var symbolInfo = semanticModel.GetSymbolInfo(memeber);
}
semanticModel.GetSymbolInfo() returns SymbolInfo with null symbol for anything that I try.
Another possible cause is that the source file for the invoked method has not been syntactically parsed and added to the compilation. You can always get some information about the method being invoked in the caller's syntax tree, but unless the invoked method has already been added to the compilation, it won't be available in the semantic model. This is painfully obvious after thinking about it for a bit. Of course the semantic model will not have information about a method that has not been processed. It is possible to add multiple syntax trees to a single compilation using AddSyntaxTrees() method. Note that this method returns a new compilation instance.
Hopefully this will save someone a little bit of time and I haven't embarrassed myself too much by posting this answer.
What I've been trying to do is convert a string of the form:
"StudentDatabase.avgHeight > 1.7"
to a lambda expression that looks like this:
() => StudentDatabase.avgHeight > 1.7;
I tried something in the lines of this:
/* String splitting and parsing occurs here */
var comparison = Expression.GreaterThan(
Type.GetType("MyNamespace.StudentDatabase").GetField("avgHeight"),
Expression.Constant(1.7)
);
var lambda = Expression.Lambda<Func<bool>>(comparison).Compile();
Of course something like this wouldn't work since the GetField() method returns type FieldInfo and not Expression.
Here's a list about useful stuff you might want to know about my sample code:
The StudentDatabase class is a static class that contains a static field avgHeight.
I have already done the part of the code that parses the string so there's no need to include it in any provided solutions.
This is just an example so you can change the string and variable/class names if you wish so.
This is not an assignment so feel free to post source code. In fact, that would be greately appreciated.
TL;DR; What I'm trying to do is use LINQ Expressions to access variables from other places of the code.
I disagree with the following comments, Linq expressions is a viable way to do this sort of thing. The below code accomplishes it. However, please consider the following code:
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
/* String splitting and parsing occurs here */
var comparison = Expression.GreaterThan(
Expression.Field(null, Type.GetType("MyNamespace.StudentDatabase").GetField("avgHeight")),
Expression.Constant(1.7)
);
var lambda = Expression.Lambda<Func<bool>>(comparison).Compile();
StudentDatabase.avgHeight = 1.3;
var result1 = lambda(); //is true
StudentDatabase.avgHeight = 2.0;
var result2 = lambda(); //is false
}
}
class StudentDatabase
{
public static double avgHeight = 1.3;
}
}
Should result2 be true or false? If you want it to be true, then you have more work to do.
I've created this as a sort of framework you can work off of. It does not use LINQ but will output the value specified by the string.
var type = Type.GetType("MyNamespace.StudentDatabase");
if (type != null)
{
var field = type.GetField("avgHeight");
if (field != null)
{
Func<bool> lambda = () => (double)field.GetValue(type) > 1.7;
}
}
There is some error checking you could add/remove. The other areas such as the > and 1.7 can be parsed elsewhere and inserted but this is how you could get a value from the strings.
Given the code:
dynamic foo = new ExpandoObject();
foo.Bar = "something";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
The output is below:
"{\"Bar\":\"something\"}"
When debugging a large json document it is hard to read - using the built in features of Newtonsoft.Json (not regex or hacks that could break things) is there any way to make the output a string with the valie:
{Bar: "something"}
If this happens to you while returning the value from a WebApi method, try returning the object itself, instead of serializing the object and returning the json string. WebApi will serialize objects to json in the response by default; if you return a string, it will escape any double quotes it finds.
So instead of:
public string Get()
{
ExpandoObject foo = new ExpandoObject();
foo.Bar = "something";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
return json;
}
Try:
public ExpandoObject Get()
{
ExpandoObject foo = new ExpandoObject();
foo.Bar = "something";
return foo;
}
Try the JToken.Parse method. I've found that even though when I view JSON objects in the debugger and they are correct, when I go to manipulate them they end up being converted to literals (i.e. backslashes are added). The JToken.Parse method seems to avoid this.
var token = JToken.Parse(text);
So in the case of the original question it would be something like:
dynamic foo = new ExpandoObject();
foo.Bar = "something";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
var token = JToken.Parse(json);
//Do stuff with token -- not json string
In my case specifically the issue was that using JObject.Add(json) would not recognize that my string was json and just insert the entire string as a single property. Once converted into a Jtoken however the JSON was interpreted correctly.
What you see in debugger when looking at the json value is the string value that you should use in a C# file to obtain the same value.
Indeed you could replace
dynamic foo = new ExpandoObject();
foo.Bar = "something";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
with
string json = "{\"Bar\":\"something\"}";
without changing the program's behaviour.
Thus, to obtain a different value, you should change how JsonConvert works, but JsonConvert conforms to the JSON standard, thus forget it!
If you are not actually serializing ExpandoObject (nor any other sealed class out of your control), you can use the DebuggerDisplayAttribute on the types that you are serializing in json, to define how the object will be shown during debug (in your code, the foo instance).
But a string is a string and VisualStudio is right: double-quotes must be escaped.
Old question but I found this,
In my case, I was looking at the JSON string in a debugger and I found that was adding the escaping.
And when I printed JSON to console, it was without escape characters. Hope it helps.
Instead of using Newstonsoft.Json you should employ the JavaScriptSerializer.Serialize Method:
dynamic foo = new ExpandoObject();
foo.Bar = "something";
var js = new JavaScriptSerializer( );
string json = js.Serialize(foo);
This method produces exactly the output you are looking for. I read about it here.
Its Just simple make the return IHttpActionResult and return the object
public IHttpActionResult Get()
{
ExpandoObject foo = new ExpandoObject();
foo = //query result
return ok(foo)
}
Hey I Just simply write out put to a file
using (System.IO.StreamWriter file =
new System.IO.StreamWriter(#"jsonGonna.txt", true))
{
file.WriteLine(json);
}
now just run the program and you will get without black slash and it good for big programs where you need to save JSON multiple times
Actually it has nothing to do with serializer. It's just because c# don't have single and double quotes concept like Javascipt does. So it can't show string with double quotes without escaping them.
But if you want to put string into html/ cshtml without any escapes you just need to tell compliler that like so:
window.MYVAR = JSON.parse('#Html.Raw(ViewBag.MyStringFromCSharp)');
In case you're getting your data from a controller view method in such a format and finding it difficult to work with in JavaScript. Below is an easy work around:
const CleanUpDifficultJSonData = difficultJSonData => {
const dummyElement = document.createElement('div');
dummyElement.innerHtml = difficultJSonData;
const cleanJSonData = JSON.parse(dummyElement.innerHtml);
return cleanJSonData;
};
const difficultJSonData = "{\"Bar\":\"something\"}";
console.log('cleanJSonData: ',
CleanUpDifficultJSonData(difficultJSonData));
[HttpGet]
public object Get(int id)
{
object result = "";
var db = new dbEntities();
var EO = new System.Dynamic.ExpandoObject() as IDictionary<string, Object>; //needed to return proper JSON without escape slashes
try
{
IEnumerable<usp_GetComplaint_Result> aRow = db.usp_GetComplaint(id);
string DBL_QUOTE = new string(new char[] { '"' });
result = "{";
foreach (usp_GetComplaint_Result oneRow in aRow)
{
System.Reflection.PropertyInfo[] properties = typeof(usp_GetComplaint_Result).GetProperties();
foreach(System.Reflection.PropertyInfo property in properties)
{
var vValue = property.GetValue(oneRow) == null ? "null" : property.GetValue(oneRow);
EO.Add(property.Name,vValue);
}
break;
}
}
catch (Exception ex)
{
result = ex.Message;
EO.Add("Error", result);
}
finally
{
db.Dispose();
}
return Ok(EO);
}