Reputation: 17701
I have class object like this as below
public class Version
{
[JsonIgnore]
public string ClassName = "Version";
[JsonIgnore]
public string Name { get; set; } = "Version 1";
.......
.......
}
I am passing this class object to the method like as below
class EpJSON
{
public Dictionary<string, Dictionary<string, object>> model = new Dictionary<string, Dictionary<string, object>>();
public void Add(dynamic v)
{
if (model.ContainsKey(v.ClassName))
{
if (model[v.ClassName].ContainsKey(v.Name))
{
model[v.ClassName][v.Name] = v;
}
else
{
model[v.ClassName].Add(v.Name, v);
}
}
else
{
Dictionary<string, object> obj = new Dictionary<string, object>() { { v.Name, v } };
model.Add(v.ClassName, obj);
}
}
public void Save(string path)
{
using (StreamWriter file = File.CreateText(path))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(file, model);
}
}
}
I am calling the Add method like as below
var model = new EpJSON();
var ver1 = new Version() { VersionIdentifier = "9.2" };
model.Add(ver1);
var ver2 = new Version() { Name = "V2", VersionIdentifier = "9.3" };
model.Add(ver2);
model.Save(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.json"));
I would like to get the suggestion from you guys is there any generic way to pass the Version
object to method Add
and I can be able to pass other object that is exactly same like as this object with extra fields
please let me know if you need more information
updated code
public void Add([dynamicObj] v)
{
if (model.ContainsKey([dynamicObj].ClassName))
{
if (model[[dynamicObj].ClassName].ContainsKey([dynamicObj].Name))
{
model[[dynamicObj].ClassName][[dynamicObj].Name] = v;
}
......
}
......
}
Upvotes: 0
Views: 104
Reputation: 11973
I would still suggest the interface way but if you absolutely want to do what you described then dynamic
keyword or reflection will do
public void Add(dynamic v)
{
Type type = v.GetType();
bool hasClassNameProperty = type.GetProperty("ClassName") != null;
if (hasClassNameProperty)
{
string className = v.ClassName;
}
bool hasNameProperty = type.GetProperty("Name") != null;
if (hasNameProperty)
{
string name = v.Name;
}
}
public void Add2(object o)
{
Type type = o.GetType();
PropertyInfo classNameProperty = type.GetProperty("ClassName");
if (classNameProperty != null)
{
string className = (string)classNameProperty.GetValue(o);
}
PropertyInfo nameProperty = type.GetProperty("Name");
if (nameProperty != null)
{
string name = (string)nameProperty.GetValue(o);
}
}
Upvotes: 0
Reputation: 622
By generic I'm not exactly sure what you mean. If you want to dynamically invoke the Add method of your EpJson
class, you can use the GetMethod function of the Type class. Here's an example using List<string>
, but it surely works with any type:
var myList = new List<string>();
var addMethod = myList.GetType().GetMethod(nameof(myList.Add));
addMethod.Invoke(myList, new object[] { "hello" });
Console.WriteLine(String.Join(",", myList)); // produces "hello"
EDIT: Okay I think I get what you mean. You have to use polymorphism to achieve this. Let's say you want to pass objects which has ClassName
and Name
properties. Then you could define an interface like:
public interface IObjectWithRequiredProperties
{
string ClassName { get; set; }
string Name { get; set; }
}
Then make your Version
class an implementor of this interface by changing the class definition to
public class Version : IObjectWithRequiredProperties
...
This will force the class to contain those properties you define on the interface. And now comes the fun part, you have to make your Add
method generic by changing it to
public void Add<TGeneric>(TGeneric v) where TGeneric: IObjectWithRequiredProperties
Now you can be sure that whatever is passed to the Add
method, it will have all the properties that IObjectWithRequiredProperties
has. Naturally you have to change the underlying dictionary to your interface's type. This is called a generic type constraint.
Upvotes: 1