I can use the .Net ConfigurationManager to store strings, but how can I store structured data?
For example, I can do this:
conf = ConfigurationManager.OpenExeConfiguration(...)
string s = "myval";
conf.AppSettings.Settings["mykey"].Value = s;
conf.Save(ConfigurationSaveMode.Modified);
And I would like to do this:
class myclass {
public string s;
int i;
... more elements
};
myclass c = new myclass(); c.s = "mystring"; c.i = 1234; ...
conf.AppSettings.Settings["mykey"] = cc;
conf.Save(ConfigurationSaveMode.Modified);
How do I store and retrieve structured data with the ConfigurationManager?
I implemented a solution as #sll suggested. But then difficulty was to create a new section to the configuration. Here is how this is done:
How to Write to a User.Config file through ConfigurationManager?
You can create own configuration section type by inheriting from ConfigurationSection class and use it to save/load any custom type information.
MSDN: How to: Create Custom Configuration Sections Using ConfigurationSection
BTW, One advice which might be helpful for you or others: One good thing is making custom configurations section class immutable (no public setters) so you can be sure that configuration cannot be changed on any stage of application life cycle, but then if you decide writing unit tests for code which relies on configuration section class and need section stub with some test values you might stuck with abilty to set property values since there is no setters. Solution is providing a new class which is inherited from your section class and specifying in constructor values using protected indexer like show below:
public class TestSectionClass: MyConfigurationSection
{
public TestSectionClass(string testUserName)
{
this["userName"] = testUserName;
}
}
Serialization.
There are numerous different ways of serializing data, so you'd need to pick one. But .NET provides a serialization API that suits a great many cases, and in working with web AJAX calls recently I find myself using JavaScriptSerializer heavily to turn things into JSON. However there are third party libraries such as protobuf-net, and so on.
The key here is to essentially turn your data into a byte or string representation that can later be deserialized back to its original structure at a later date, allowing you to store it in a medium between then, such as in configuration files or transmission over networks etc.
As per #sll's answer, .NET has another facet meaning it can handle serialization of data in and out of custom configuration sections; whether you want to begin specifying types explicitly for this purpose or not is your call. Bottom line is the same, serialize, somehow.
Related
I'm triying to read some data form an OPC UA server using opc-ua-client library. Managed to connect to server and read some simple variables, but facing issues when reading structured values. However, I'm able to browse those structured values using 3rd party tools, such as UAExpert.
This is the code snippet:
var readRequest = new ReadRequest
{
NodesToRead = new[] { new ReadValueId { NodeId = NodeId.Parse(nodeId), AttributeId = AttributeIds.Value } }
};
var response = channel.ReadAsync(readRequest).Result;
var result = response.Results[0].GetValueOrDefault<ExtensionObject>();
The point is: how should I cast the ExtensionObject into the underlying real object? Response's body is binary serialized into a System.Byte[] field, and don't know how to deserialize it. I know the fields and types of the structure, so defined it in the code (even decorating with the namespace provided by the server) as follow:
[BinaryEncodingId("nsu=urn:OMRON:NxOpcUaServer:FactoryAutomation;i=5005")]
private class MES_WRITE_STRUCT : Structure
{
uint Message_NUM { get; set; }
//Some other fields
DateTime Time_Stamp { get; set; }
}
Things I've tried (and failed) so far:
Brute-force cast:
var eObject = (MES_WRITE_STRUCT)result.GetValueOrDefault<ExtensionObject>();
Read the response as the expected type rather than using generic object:
var eObject = result.GetValueOrDefault<MES_WRITE_STRUCT>();
Use the Variant property rather than Value (same result as
using Value):
result.Variant.GetValue();
Create a binary reader and attempt to deserialize it into expected
class.
Maybe I'm using a wrong approach and structured values should be read in a different way. Or even the library does not support structured variables (not much documentation available). Or just using an incorrect type when defining custom class in .NET and hence casting is failing.
I'm totally stuck, any information or guidance is wellcome.
PS: I'm not tied to this library and can switch to another one (preferably with no licenses, but if really worths can consider buying).
One way would be to use the XML description of the information model (so called nodesets) you wish to consume and use the model compiler from OPC Foundation to generate C# classes out of it. Those classes can be integrated in your solution and used for deserialization.
And example (using the OPC Foundation libraries) could be found here
Another way is the OPC Foundation .NET Standard client which has an extension library nuget package called complex client. It contains the logic to read the structured type definition from a server from a dictionary (V1.03) or using DataTypeDefinition (V1.04).
Based on the obtained type definition the classes for the structured types can be emitted for encoding/decoding the byte string in the extension object at runtime. Please open issues if the complex client has difficulties to decode your structured type.
How to create AutoMapper configuration when the source and destination classes are totally different ? I want to create a mapping between some external classes (which cannot be changed) and my classes which I'm gonna persist in the db. I could persist the entire external class , but I dont want to do that to save space. I'm using .net core 2.0.
For ex: I've an external class like below :
A
{
B {
b1;b2;b3;
}
C {
c1;c2;c3;
}
}
The above needs to be mapped to my class defined like below :
A
{
Optmized_BC{
b1;
b2;
c1;
}
c2;
}
What's the best way to create AutoMapper configuration in the above case ? Should I call CreateMap for every pair of source/destination variable ? Is there a way where I can map all variables inside one CreateMap call (using some clever linq maybe ?)
You could persist your data as JSON in the database, then it would be easy to deserialize it to the other class using Newtonsoft JSON library. You have to decide if it's easier than writing the mapper function for each case. The same structure/naming would be deserialized automatically, otherwise, you could use 'dynamic'.
Just to give you an idea:
var result = JsonConvert.DeserializeObject<dynamic>(json);
A a = new A();
a.Optmized_BC.b1 = result.B.ToObject<B>().b1;
I would suggest to use the explicit mapper and cover it with the unit tests
I have defined a class and i need to store some objects of that class for future reference. Can i store these objects into an azure database i've created ?
In order to save an object (instance of a Class) to whatever medium (SQL Server, Azure SQL Database, Azure Table Storage, Blob Storage, local File System, whatever you come up with), you will need to serialize it. Then store the result of serialization to the medium of your choice. Next, when you want to use the persisted state of the object, you will have to deserialize it.
There are different serialization formatters, like XML, JSON, Binary, etc. Which one to use, depends on the where and how you are going to store the object. The most important however, is that, in order one object to be serialized, the defining Class should be marked with SerializableAttribute. And the drama begins when you want to serialize object which is part of 3rd partys API.
If it is your type - just mark it as Serializbale, serialize and store it. Pretty stright-forward process.
If you don't have access to the source code to explicitly mark class as Serializable, you could possibly use the Serialization Surrogate to serialize your object. But, you might have issues when deserializing. For example, if the API Class you use does not have a public contructor. Or if it does not provide setters for some of the properties, etc., etc. At the end, if a Type is not designed to be serializable, and is part of 3rd party API, there might be a ton of reasons serialization/deserialization might fail.
At the end, you could try using the Json.NET serializer (install via NuGet):
var someObj = new DummyClass
{
ID = Guid.NewGuid(),
IntID = 102934,
Name = "My Super Hero Name"
};
string json = JsonConvert.SerializeObject(someObj);
Console.WriteLine(json);
var otherObj = JsonConvert.DeserializeObject<DummyClass>(json);
Console.WriteLine(otherObj.ID);
Console.ReadKey();
and check if it correctly serializes/deserializes your object. If everything is fine - use the json string to save it into Database of your choice.
Our system complexity has risen to the point that we need to make permission names tied to the client from the database more specific. In the client, permissions are referenced from a static class since a lot of client functionality is dependent on the permissions each user has and the roles have a ton of variety. I've referenced this post as an example, but I'm looking for a more specific use case. Take for instance this reference, where PermissionAlpha would be a const string:
return HasPermission(PermissionNames.PermissionAlpha);
Which is great, except now that things are growing more complex the classes are being structured like this:
public static class PermissionNames
{
public static class PermissionAlpha
{
public const string SubPermission = "PermissionAlpha.SubPermission";
}
}
I'm trying to find an easy way to reference PermissionAlpha in this new setup that will act similar to the first declaration above. Would the only way to do this be to resort to pulling the value of the class name like in the example below? I'm trying to keep all the names in one place that can be reference anywhere in the application.
public static class PermissionAlpha
{
public static string Name { get { return typeof(PermissionAlpha).Name; } }
}
** Edit ** - Added missing permission name.
Maybe this would be too big of a change for you with the size of your project, but we have all of our business objects split into partial classes. One is for manual changes and one gets generated. During code-generation, we write the permission keys into the generated side of the partial classes from our "single source of truth". We're using a set of classes as our source of truth and CodeDom to generate, but you could also use a database as your source and use T4, CodeSmith, or others to generate.
Why not create reflectable attribute(s) on the classes in question? That way one can add all the extra information required. I provide a way of divining attributes on my blog article entitled:
C# Using Extended Attribute Information on Objects
HTH
Currently, I've created a class with ~30 properties to be set. This is done to build up a URL request later on(ie, "http://www.domain.com/test.htm?var1=a&var2=b...&var30=dd").
The issue I'm facing is the property names don't necessarily match the query variable names(this is intended to be different). For example, I may have a variable titled "BillAddress", whereas the query variable will need to be "as_billaddress".
I have no control over the query variable naming scheme as these are set at an external source.
One possible solution I've used is creating a custom attribute and decorating the properties with their respective query counterparts:
[CustomQueryAttribute("as_billaddress")]
string BillAddress{get;set;}
To retrieve the attribute though, requires a little reflection and due to the larger number of properties, I was curious if there is a neater way to accomplish this functionality. Not so much as setting/retrieving custom attributes without reflection, but being able to tie an alternate string variable to any property.
I've also pondered about setting each variable up as a sort of KeyValuePair, with each key representing the query counterpart, but I didn't get too far in that thought.
To summarize/clarify my above backstory, what would you do to associate a string with a property(not the value of the property)?
As always, any comments are greatly appreciated.
I would probably stick with a custom attribute, but the other potential option would be to do something like hold a static Dictionary that had string and property info (or property name), so you could get/set the property directly via this.
Something like:
static Dictionary<string, PropertyInfo> propertyMap = new Dictionary<string, PropertyInfo>();
static MyClass()
{
Type myClass = typeof(MyClass);
// For each property you want to support:
propertyMap.Add("as_billaddress", MyClass.GetProperty("BillAddress"));
// ...
}
You could then just do a dictionary lookup instead of using reflection in each call... This could also be setup fairly easy using configuration, so you could reconfigure the mappings at runtime.
A custom attribute seems like the best option to me - the framework seems to do this a lot as well (specifically with serialization).
If you look at popular ORM mappers then nearly all either use custom attributes or some kind of XML mapping file. The advantage of the latter is that you can modify the mapping without recompiling your application - the downside is that it hurts performance. However, I'd say your choice seems perfectly reasonable.