I built a dynamic Survey type application where users can set up their template of questions/attributes that need to be captured. A template can have multiple sections, where each section contains multiple questions/attributes.
We write out the data in JSON according to the template, to be consumed or sent by webhooks, for external systems. Rather than developing a layer for each external integration to deserialize our system's object and transform it for the external system's consumption, I was thinking of writing dynamic mapper that uses a configuration schema(maybe JSON) that will map your source to your destination. Which will be great, as soon as either the source or destination changes, the configuration can just be adjusted accordingly, without having to change code and re-publish.
I'm using this system as an example, but I'm seeing multiple applications for different use cases, with the main one being a source API that needs to integrate with multiple external API's.
Source JSON example:
{
"Section1": {
"S1Attribute1": "S1Attribute1Answer",
"S1Attribute2": "S1Attribute2Answer",
"S1Attribute3": "S1Attribute3Answer"
},
"Section2": {
"S2Attribute1": "S2Attribute1Answer",
"S2Attribute2": "S2Attribute2Answer"
}
}
Destination 1 Example:
{
"SectionsFlattened": {
"S1Attribute1": "S1Attribute1Answer",
"S1Attribute2": "S1Attribute2Answer",
"S1Attribute3": "S1Attribute3Answer",
"S2Attribute1": "S2Attribute1Answer",
"S2Attribute2": "S2Attribute2Answer"
}
}
Destination 2 Example:
{
"NewSection1Name": {
"NewS1Attribute1Name": "S1Attribute1Answer",
"NewS1Attribute2Name": "S1Attribute2Answer",
"NewS1Attribute3Name": "S1Attribute3Answer",
"NewSection2Name": {
"NewS2Attribute1Name": "S2Attribute1Answer",
"NewS2Attribute2Name": "S2Attribute2Answer"
}
}
}
This is pretty simple examples of just moving properties around, but the possibilities are endless of how one would need to transform it.
It feels like a problem that somebody would have investigated or solved maybe, but in all my research I don't seem to find anything concrete, or I'm struggling to find a good starting point - maybe I'm approaching the problem incorrectly. Any suggestions/guidance/articles/libraries would be appreciated.
Related
What I am trying to do:
I am working on a chat bot service where I have different channels of access. On one channel I want to use my Customer.resx file and on another channel I want to use my Worker.resx file.
The problem:
I know how localization works to switch between Worker.en-US.resx and Worker.es-MX.resx, but I am unsure how to switch from one normal resx file to a completely different context one. These will each be translated into other languages so I can't simply use Customer.en-US.resx and Worker.es-MX.resx as a workaround. I do know that I can build a custom culture using the CultureAndRegionInfoBuilder, but I would rather do this in a simpler way than that, something along the lines of how you do localization. I am currently building custom cultures using this method and I have Resources.worker-en-US.resx and similar for customer, but this is a round-about way and I know there must be a better way.
For clarification I know I can grab a resource file with ResXResourceSet, but the idea was that I would like to have two separate resource files with localization for each (worker.en-US and customer.en-US).
I would combine both of these as into one because resx's are really tied to cultures/languages. You can use a strategy pattern to get the right strings at the right time.
interface IStrings { string Foo { get; } }
class WorkerStrings : IStrings { ... }
class CustomerStrings : IStrings { ... }
I want to build a web app with Javascript for the front end and C# for the back end and I want to determine the value of GraphQL.
For my C# back end I use a GraphQL implementation named GraphQL for .NET.
For my front end, I would like to use Relay as it plays well with ReactJS.
Now for my back end, I implemented a sample schema like in one of the examples which looks like this:
public class StarWarsSchema : Schema
{
public StarWarsSchema()
{
Query = new StarWarsQuery();
}
}
In my front end, I now need to tell Relay somehow about this schema. At least this is what I understood when walking through the tutorials, because for some reason the GraphQL queries needs to be transpiled.
This is an example as how I would like to load all Droids:
class Content extends React.Component<ContentProps, { }> {
...
}
export default Relay.createContainer(Content, {
fragments: {
viewer: () => Relay.QL`
fragment on User {
query HeroNameQuery {
droids {
id
name
}
}
}
`,
}
});
In one of the examples for Relay, I have seen that the babel-relay-plugin is used for conversion. It gets a schema file (JSON). The Getting Started Guide of Relay shows, how to create such a schema with graphql-js and graphql-relay-js.
Now my questions:
Do I really need to create schemas on the front and on the back end?
What is the point of teaching Relay my schema, as the back end already uses the schema to return the well formed data?
What is the benefit at all from using Relay in this scenario? What would I lose when I would just access the backend via a regular REST endpoint along with a GraphQL query as a parameter?
You need schema only on the backend and you can download schema.json from your backend using example at the bottom part of this document: https://facebook.github.io/relay/docs/guides-babel-plugin.html
Relay need schema to correctly construct queries and understand types of returned data.
Relay wraps your React components and fetch/provide all necessary data for rendering. Have many features out of the box like data caching, query consolidation, so with Relay you don't need to fetch anything and worry about how data provided to your component, you just need to write queries and components.
In the application I'm developing, the same software package serves many industries, and those industries have different vocabulary for what is essentially the same thing. The application is a C# server, to which a WPF desktop app makes socket-based XML requests.
For example, some customers may call something an "Item", some call it a "Part", or some call it a "SKU".
The goal is for the application to be able to relabel itself based on a "Vocabulary" setting that we create for the user. Typically, a given customer's vocabulary will only differ by perhaps 5-25 words/phrases out of the entire application. These custom vocabularies are specific to/created by the customer, and wouldn't be kept with the main application distribution.
My initial thought was to do this with custom CultureInfo, (e.g. "en-AC" for "Acme" company), supply just values that differ from the base en-US in that resource file.
The en-AC.resx resource could be kept on the server, loaded by the server, and also transmitted for loading into the WPF client app.
Problem with that thus far seems to be that the ResourceManager does not correctly pick strings for custom cultures, a'la this thread, and I've not been able to solve that yet. As well, as the app is ClickOnce deployed, we may not have permission to register a new culture.
My next thought, since the number of phrases to modify is so small, was to replace the resource value at runtime, but that seems to be a bit of a no-no as well, searching around.
So, thought I would ask the community for their suggestions on how to handle this.
Open to suggestions and ideas...
Because it's only about a few words I think I'd do it via a naming convention. Suppose you defined the string key "MyCompany". You usually access this way:
string myString1 = Properties.Resource.MyCompany;
But it is also ok to Access it that way:
string myString2 = Properties.Resource.ResourceManager.GetString ("MyCompany")
It's exactly the same (but dealing with strings as identifiers - which is somewhat error prone). What you now can do is to check for a special name first that you syntesize like "MyCompany_AC". The drawback is you need your own wrapper for each string:
string MyCompany
{
get
{
string myString = Properties.Resource.ResourceManager.GetString ("MyCompany_" + theCompanyPostfix);
if (myString == null)
{
myString = Properties.Resource.ResourceManager.GetString ("MyCompany");
}
return myString;
}
}
I am creating a tile-based game in XNA and will be loading the level information from xml files. I have no problem with loading xml data but I would like feedback on the approach I'm thinking of using for reading the xml file.
The code has a class hierarchy such that:
A Level class contains:
- a collection of TileLayers
- a collection of Tilesets
A TileLayer class contains
- a collection of Tiles
A Tileset class contains:
- a collection of TilsetTiles
A TilesetTile class contains:
- a TileId
- a collection of TileProperties
- a TileRectangle
Each of the above classes requires some information from the xml level file.
When I load a level I would like to simply call Level.Load();
My intention is that each class will have a Load() method that will:
1. Load any specific info it needs from the xml file.
2. Call Load() on its children.
The problem I see is that the code for processing the xml will be scattered around in different files making changes difficult to implement (for instance if I decide to encrypt the xml file), and no doubt breaks several aspects of the SOLID principles.
I have this idea that I could create an xmlLevelReader class whose sole purpose is to read an xml level file.
This class could then expose methods that can be called from the Load() method in each of the classes described above.
For example the TileLayer class Load() method could call xmlLevelReader.GetTiles() which would return an IEnumerable<Tile>
Do you think this approach will work?
Can you foresee any difficulties?
Is this approach too simplistic/complicated?
Any constructive criticism welcomed!
Thanks
Based on your comment, I see that you are using Tiled Map Editor. This lead me to suggest that you use TiledLib. Here is a brief explanation of how you can get up and running with importing your .tmx files for use in game.
Content Pipeline Overview
File -> Content Import -> Content Process -> Content Write -> .xnb -> ContentRead -> Game Object
TiledLib
TiledLib only handles the ContentImporter part of the above diagram. It will essentially handle reading the .tmx XML and allow you to process the data into whatever objects you need at run time. Fortunately, the TiledLib author has provided a Demos section in the download as well.
Basic Tiled Map Processor Demo
BasicDemo main game project which contains the ContentManager.Load call.
BasicDemoContent project which has the .tmx file from Tiled
BasicDemoContentPipeline project which has the ContentProcessor
TiledLib which has the ContentImporter
You really only need to worry about how the ContentProcessor works because TiledLib handles all the importing for you. Although I do suggest looking through the different classes to understand how it is deserializing the XML (for educational purposes).
The example ContentProcessor in the Basic Demo project takes in a MapContent object from the ContentImporter (TiledLib) and outputs a DemoMapContent object which is serialized to .xnb at build time and deserialized to a Map object at run time. Here are the classes that represent the map after being processed completely:
[ContentSerializerRuntimeType("BasicDemo.Map, BasicDemo")]
public class DemoMapContent
{
public int TileWidth;
public int TileHeight;
public List<DemoMapLayerContent> Layers = new List<DemoMapLayerContent>();
}
[ContentSerializerRuntimeType("BasicDemo.Layer, BasicDemo")]
public class DemoMapLayerContent
{
public int Width;
public int Height;
public DemoMapTileContent[] Tiles;
}
[ContentSerializerRuntimeType("BasicDemo.Tile, BasicDemo")]
public class DemoMapTileContent
{
public ExternalReference<Texture2DContent> Texture;
public Rectangle SourceRectangle;
public SpriteEffects SpriteEffects;
}
A Map contains a tile width, tile height, and a list of MapLayers.
A MapLayer contains a width, a height, and a list of Tiles.
A MapTile contains a texture, a source rectangle (proper rectangle in the tileset), and optional sprite effects (I've never used any).
How It's Made
I suggest reading the comments of the ContentProcessor to understand what is happening, but in brief, this is the basics:
Load texture data for tile set
Get source rectangles for each tile from within the texture
Iterate over all layers of the map
For each layer, iterate over all tiles
For each tile, get the proper texture and source rectangle
Assign all data from the input to the output properly
Caveats
As long as you stick to basic types (vague, I know), you also do not need to worry about ContentWriter and ContentReader parts of the content pipeline. It will automatically serialize and deserialize the .xnb files at build and run time, respectively. See a question I asked about this: here.
Also, you'll notice that if you're using object layers from within Tiled, the demo does not show you how to process those. TiledLib does properly import them, you just need to pull the data out and stick it in your proper classes. I'll try to edit this answer later with an example of how to do that.
If you are just wanting to load in XML without manipulating the data at all, you can just use the built in XNA Content Serializer.
Essentially you define a class which maps to your xml format, and then read the XML into an instance of that class.
For example. Here I define the class I want to load into:
SpriteRenderDefinition.cs
I chose this one because it has nested classes like the case you describe. Note that it goes into the ContentDefinitions project of you XNA solution.
Now here is the xml file that fills in the content of a SpriteRenderDefinition:
Sprite.xml
The format of that XML maps directly to the member names of SpriteRenderDefinition.
And finally, the code to actually load that XML data into an actual Object at runtime is very straight forward:
SpriteRenderDefinition def = GameObjectManager.pInstance.pContentManager.Load<SpriteRenderDefinition>(fileName);
After calling that line, you have a SpriteRenderDefintion object populated with all the content of the XML file! That is all the code I wrote. Everything else is built into XNA. It's really quite slick and useful if you take an hour or so to figure it out!
I want to make a Configuration Data Manager. This would allow multiple services to store and access configuration data that is common to all of them.
For the purposes of the Manager, I've decided to create a configuration class object - basically what every configuration data entry would look like:
Name, type, and value.
In the object these would all be strings that discribe the configuration data object itself. Once it has gotten this data from its database as strings, it would put it into this configuration object.
Then, I want it to send it through WCF to its destination. BUT, I don't want to send a serialized version of the configuration object, but rather a serialized version of the object discribed by the configuration object.
The reason I'd like to do this is so that
The Data Manager does not need to know anything about the configuration data.
So I can add configuration objects easily without changing the service. Of course, I should be able to do all of the CRUD operations, not just read.
Summary:
Input: string of name, type and value
Output: Serialized output of the object; the object itself is "type name = value"
Questions:
Is this a good method for storing and accessing the data?
How can I/can I serialize in this manner?
What would the function prototype of a getConfigurationData method look like?
I have decided to go in a different direction, thanks for the help.
Is this a good method for storing and accessing the data?
That is difficult to answer, the best I can give you is both a "yes" and a "No". Yes, It's not a bad idea to isolate the serialization/rehydration of this data.... and No, I don't really care much for the way you describe doing it. I'm not sure I would want it stored in text unless I plan on editing it by hand, and if I'm editing it by hand, I'm not sure I'd want it in a database. It could be done; just not sure you're really on the right track yet.
How can I/can I serialize in this manner?
Don't build your own, never that. Use a well-known format that already exists. Either XML or JSON will serve for hand-editable, or there are several binary formats (BSON, protobuffers) if you do not need to be able to edit it.
What would the function prototype of a getConfigurationData method look like?
I would first break-down the 'general' aka common configuration into a seperate call from the service specific configuration. This enables getConfigurationData to simply return a rich type for common information. Then either add a extra param and property for service specific data, or add another method. As an example:
[DataContract]
public class ConfigurationInfo
{
[DataMember]
public string Foo;
...
// This string is a json/xml blob specific to the 'svcType' parameter
[DataMember]
public string ServiceConfig;
}
[DataContract]
public interface IServiceHost
{
ConfigurationInfo GetConfigurationData(string svcType);
}
Obviously you place a little burden on the caller to parse the 'ServiceConfig'; however, your server can treat it as an opaque string value. It's only job is to associate it with the appropriate svcType and store/fetch the correct value.