I have a table in the database for various settings in my application. These settings can be added to or changed at any time. I would like to pull them out of the db into an object and reference them in both my server code (C#) and client code (JS).
SettingGroup SettingName type value
Core defaultPagingSize numeric 5
Core pagingType text dynamic
Ecommerce showGallery boolean true
In javascript I can just put them into a JSON object and reference them like this:
var size = settings.core.defaultPagingSize;
Is there a similar way I can do this in C#?
int size = settings.core.defaultPagingSize;
No.
The new dynamic keyword that will be added for .NET and C# 4.0 will handle what you're seeking, but in the current .NET and C# versions, there's no support for this.
You should be able to get this to work though:
int size = settings["core"]["defaultPagingSize"].ToInt32();
or something similar.
In .NET, the most immediate answer would be to use a dictionary (perhaps nested) of some kind. C# 4.0 introduces some dynamic concepts, but you'd need to write a fair bit of code to get it to behave like javascript.
Alternatively, store them as typed records in a flat list and use LINQ:
var setting = settings.Single(x=>x.Group == "Core"
&& x.Name == "defaultPagingSize");
int value = int.Parse(setting.Value);
Related
I've started a Blazor Web Assembly Project that makes use of Radzen components. I'm trying to create a search through my API, and I would like to use a combination of their DataGrid and new DataFilter components to do so. It looks like the best way I can do this is by tapping into the DataFilter's ViewChanged event callback, within which I can access an IQueryable.
So if I were to filter Person data by name and print out the resultant IQueryable in this callback, I get something like this:
TheMill.Shared.Models.Mill.Person[].Where(Param_0 => (IIF((Param_0.DisplayName1 == null), "", Param_0.DisplayName1) == "Ben"))
Is it possible to send this string to my API endpoint, run the query, and return the Person records that match? I'm hoping I'm headed in the right direction by looking into the ParseLambda function from Dynamic LINQ.
The approach you're describing is fraught. The .ToString() representation of IQueryables is not designed to be parsed back into a query. It is not guaranteed to contain all the information you need in your query (for example, if you use a closed-over variable in your your lambda instead of a hard-coded string), and it can change from one version of .NET Framework to the next.
Instead, I'd recommend looking into something like OData, which is a standards-based way of creating a query string that can be translated into an Entity Framework query. In fact, Radzen's Blazor DataGrid natively supports OData bindings.
I’m developing a mobile application which among other things, it receives data from medical devices via Bluetooth. To this end, I’m using an Android SDK in JAR via binding to my Xamarin project. Here’s the class that holds the returned data from the decompiled JAR:
package com.contec.jar.contec08a;
import java.util.ArrayList;
public class DeviceData
{
public ArrayList<byte[]> mData_blood = new ArrayList();
public ArrayList<byte[]> mData_oxygen = new ArrayList();
public ArrayList<byte[]> mData_normal_blood = new ArrayList();
}
What is of interest is the mData_blood. Each element of the array list corresponds to a patient. Each byte array is the medical data for each patient. The Xamarin framework makes some changes, i.e. the name of the property becomes MDataBlood.
Problem: when I receive the above class and property, the casting fails BUT NOT in the debugger. Here’s what I mean: the ‘as’ operator that implement the cast fails (returns null) but in the debugger the very same expression correctly shows the data.
What’s more, the ‘is’ operator returns false in runtime (the canDo variable is false) but true in the debugger. I’ve tried all methods of casting I’m familiar with, even using –but not mixing – Android objects. The highlighted line which casts the IList to List produces a nice exception. I’m at a total loss. Any suggestions would be greatly appreciated.
Here's the screenshot from the debugger which illustrates all the above:
Edit1: The MDataBlood[0] evaluates as generic Java object. When reviewing its properties, its isArray is set to true. By checking the decompiled source of the SDK, I determined that is indeed byte array.
In Xamarin, there are some castings that might fail when the objects come from java types. In that cases you should use JavaCast<TResult> instead of a regular casting.
Try this, instead of your current approach:
// Since MDataBlood is exposed as an IList property of MDeviceData,
// we first need to cast it to IJavaObject
var dataBloodRaw = (IJavaObject)dm.MDeviceData.MDataBlood;
// Then we have access to its JavaCast method
var dataBlood = dataBloodRaw.JavaCast<JavaList<byte[]>>();
JavaList<T> extends Java.Lang.Object, so it can be used as the TResult parameter for JavaCast<TResult>. Also, it implements IList, so you should be able to loop through it.
Anyway, if you need a List<byte[]> you can use the casted JavaList for creating it:
var dataBloodList = dataBlood.ToList();
Or, alternatively
var dataBloodList = new List<byte[]>(dataBlood);
Yet another thing you could just try is to Java-cast dataBloodRaw to a JavaList<object> and then loop through its objects, trying to cast each one of them as a byte[].
Plan B
If none of the above works, I suggest you to take a look at this answer where it is suggested to disable linking for Release, which can be done in your project properties:
Keep in mind that a side effect of this last option will be the impact on the final size of your application.
I'm using IronPython as a scripting language in my C# application. One of the "features" that I've implemented is the ability for a script to persist values, which are then exposed to the next script being executed. This is achieved by passing the value(s) to be stored to a C# class, exposed to the script by the "host" application. The code to store a value looks something like this:
store.set("xyz", 123)
('store' is the variable through which the C# object is exposed).
Internally the C# class stores these name/value pairs in a Dictionary<string, object>. When the script finishes executing it serialises the dictionary using Json.Net (var json = JsonConvert.SerializeObject(dict)) and writes the resulting string to file.
When the next script is run, the "host" C# application reads and deserialises the file (JsonConvert.DeserializeObject<Dictionary<string, object>>(s)) and exposes the name/value pairs to the script via the same C# class, which the script can access like this:
my_var = store.get("xyz")
This feature has been working fine with simple types such as ints and floats, but one of our users now needs to persist a list of ints. It works to a fashion - the list gets persisted and exposed to the next Python script, but at this point it is now a JArray type (something to do with Json.Net it seems). This doesn't play nicely with the Python code (which is expecting a list of ints).
I guess the simplest fix is to convert this JArray to a Python int list. But how?
Alternatively it would be nice if the issue could be "fixed" in the C# class (casting?), to avoid users from having to do this conversion in their scripts. However I don't want to change the de/serialisation process to the extent that it no longer reads users' existing data files. Thoughts?
I've found a solution with only minimal impact on script authors. In my C# code, after deserialising the file, I go through the dictionary looking for items with a value of type JArray, and convert them to arrays:
var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
var keys = dict.Keys.ToList();
foreach (var key in keys)
{
var jarray = dict[key] as JArray;
if (jarray != null)
{
dict[key] = jarray.ToObject<object[]>();
}
}
These arrays are then exposed to the Python script as before; as they are C# arrays the script authoer must convert to Python lists, which is trivial:
my_var = list(store.get("xyz"))
Context: ClearScript, JScript, C#, Windows, Azure
In my ClearScript-enabled projects, I have a Dictionary<string,object> that I use for passing data into, around inside and back out of evaluated scripts.
On the C# side I have
static Dictionary<string, object> Settings = new Dictionary<string, object>();
and then later on
JSengine = new JScriptEngine(WindowsScriptEngineFlags.EnableDebugging | WindowsScriptEngineFlags.EnableJITDebugging);
and
JSengine.AddHostObject("CSSettings", Settings);
On the JScript side I have things like
CSSettings.Add("your API key", CSConfig.Retrieve("api.key"));
for setting values.
The challenge at the moment is updating a value in the Dictionary. The following works
CSSettings.Item("id") = Wfm_AccNumber;
it's just that it's non-standard JScript. What's more the JSHint tool that I'm using inside of Notepad++ complains.
I could do a .Remove() before the .Add(), I suppose but is there a better way?
The following should work:
CSSettings.Item.set("id", Wfm_AccNumber);
value = CSSettings.Item.get("id"); // or CSSettings.Item("id")
This may look a bit clunky, but it's standard JavaScript and should work with all .NET indexers (which aren't always named "Item", and can have more than one parameter).
I am implementing Code Generation for WindowsForm control at Design-Time, using a Custom CodeDomSerializer.
Here is what I have.
A user control i.e. MyControl written
in C#.
MyControl has a property
MyControlProperty of type ObjectXXX
that is accessible publicly.(like
myControl.MyControlProperty).
The type ObjectYYY has a public property
PropertyXXX of type Collection.
The ObjectXXX has a internal field of type ObjectYYY.
The ObjectXXX should be initialized by passing Collection (which
is nothing but ObjectYYY.PropertyXXX).
The code generated should be as given in the code snippet below.
Line1. NamespaceX.NamespaceY.ObjectXXX x = new NamespaceX.NamespaceY.ObjectXXX(NamespaceX.NamespaceY.ObjectYYY.PropertyXXX);
Line2. myControl.MyControlProperty = x;
I succeeded in generating the aforementioned code at Design-Time by writing a custom CodeDomSerializer FOR C# Language.
But, if i use MyControl for developing an application in C++ Language, the DOT operator is serialized for both ScopeResolution and Pointer-To-Member operator.
What I am doing for code in Line1 is,
string fullyQualifiedName = "NamespaceX.NamespaceY.ObjectYYY.PropertyXXX"; // HERE VARIABLE NAME IS HARDCODED WITH TWO TYPES OF OPERATORS
CodeExpression[] parameters = new CodeExpression[] {new CodeVariableReferenceExpression(fullyQualifiedName);};
CodeStatement code = new CodeVariableDeclarationStatement(typeof(ObjectXXX), "objectXXX1", new CodeObjectCreateExpression(new CodeTypeReference(typeof(ObjectXXX)), parameters));
generatedCode.Add(code); //generatedCode has the final code
For Line2,
CodeExpression codeLhs = new CodeVariableReferenceExpression(myControlVariable + "." + "MyControlProperty"); // HERE Pointer-To-Member IS HARDCODED AS DOT
CodeExpression codeRhs = new CodeVariableReferenceExpression("objectXXX1");
CodeAssignStatement codeAssignStmt = new CodeAssignStatement(codeLhs, codeRhs);
generatedCode.Add(codeAssignStmt); //generatedCode has the final code
Obviously the C++ Designer generated code should have '::' operator(and not DOT) for the ScopeResolution and '->' for the Pointer-To-Member resolution. I was not able to figure out how to make the code serialization for any CLR supported language.
How to solve this problem?
-Thanks a bunch
Dattebayo
Thanks for the quick reply.
I found the solution.
What i need was generating code containing property access and generating code for of .NET types.
To generate code that accesses a property, one should use CodePropertyReferenceExpression. This solves my problem with Line2.
To generate code that contains a Type, one should use Code CodeTypeReferenceExpression.
This combined with CodePropertyReferenceExpression solved problem with Line1.
Now, I am able to generate code properly w.r.t. the Language in use.
//For C# The code would be
NamespaceX.NamespaceY.ObjectXXX x = new NamespaceX.NamespaceY.ObjectXXX(NamespaceX.NamespaceY.ObjectYYY.PropertyXXX);
this.myControl.MyControlProperty = x;
//For C++ The code would be
NamespaceX::NamespaceY::ObjectXXX x = new NamespaceX::NamespaceY::ObjectXXX(NamespaceX::NamespaceY::ObjectYYY::PropertyXXX);
this->myControl->MyControlProperty = x;
Not sure if this will help, but have you looked at MyGeneration its a multi language code generator written in .Net. It doesn't use CodeDomSerializer, but it does generate good code - maybe it'll solve your underlying problem without having to re-invent the wheel?