I am trying to create a configuration file using Json that will hold configuration for various types of objects.
Consider this file:
{
"cameras": [
{
"type": "Some.Namespace.CameraClass",
"assembly": "Some.Assembly",
"configuration": {
"ip": "127.0.0.1",
"port": 8080
}
}
]
}
At runtime I will use the two "type" and "assembly" properties to construct an object supporting a specific interface, and then I would like to load the configuration into that object.
However, at compile time I do not know the type that "configuration" would map to. I would like to retain it as a json "property" and feed that into the camera object, and then let that object deserialize the json into the right type.
As such I would like to just "carry" the part of the configuration file containing configuration for a particular camera type with me into the object itself, and let it deal with it, treating it like a black box while I carry it like that. The structure of that part should be preserved since I would like full fidelity when creating the configuration types for each camera implementation, even adding subobjects if necessary.
For this particular camera I would configure an IP address and a port, for some other camera I would require authorization data, and for some other camera something completely different.
I would like for the property that would hold this configuration to just get the Json directly, still as a string.
Is this possible?
Here is a LINQPad example that has some bits commented out:
void Main()
{
const string configurationFile = @"[
{
""type"": ""UserQuery+Camera1"",
""configuration"": { ""id"": 10 }
},
{
""type"": ""UserQuery+Camera2"",
""configuration"": { ""name"": ""The second camera"" }
}
]";
var cameras = JsonConvert.DeserializeObject<Camera[]>(configurationFile);
foreach (var camera in cameras)
{
var type = Type.GetType(camera.Type);
var instance = Activator.CreateInstance(type, new object[0]) as ICamera;
// instance.Configure(camera.Configuration);
}
}
public class Camera
{
public string Type { get; set; }
public JObject Configuration { get; set; }
}
public interface ICamera
{
void Configure(string json);
}
public class Camera1 : ICamera
{
private class Configuration
{
public int Id { get; set; }
}
public void Configure(string json)
{
JsonConvert.DeserializeObject<Configuration>(json).Dump();
}
}
public class Camera2 : ICamera
{
private class Configuration
{
public string Name { get; set; }
}
public void Configure(string json)
{
JsonConvert.DeserializeObject<Configuration>(json).Dump();
}
}
The two commented out bits, namely the property in the Camera class, and the call to the Configure method, is what I'd like working.
Is there something I can tag that property with, or some other type I can pick for that property, that would make this work?
I know I can make the property dynamic, which would stuff a JObject into it, but then each Configure method of each camera implementation would have to deal with a JObject and not a known non-dynamic type.
ipandport, or indeed any class representing the configuration anyway. You could potentially try making the property typeJObject, but again you wouldn't have intellisense. I'm not sure how you're expecting to get Intellisense for this at all...Camera.Configurationwouldn't be of the concrete type at compile-time, so how would you expect Intellisense to work? If I typecamera.Configuration.what properties would you expect to see? As I say, it's possible that JObject would give you what you want, but I haven't tried it.