I'm at loss here. I want to refactor a part of the code that uses no abstract classes. I'm familiar with json2csharp. That converts a JSON file to the C# classes so it can be easily deserialized.
Is there a similar site/tool that accepts as input several C# classes and generates basic abstract classes based on those?
This would make the refactoring easier as I don't need to create all the different abstract classes.
Very simple example:
Input:
public class TestClass1
{
public string TestID { get; set; }
public string TestName { get; set; }
public int TestValue1 { get; set; }
public TestClass1()
{
}
}
public class TestClass2
{
public string TestID { get; set; }
public string TestName { get; set; }
public int TestValue2 { get; set; }
public TestClass2()
{
}
}
Output:
public abstract class ATestClass
{
public string TestID { get; set; }
public string TestName { get; set; }
protected ATestClass()
{
}
}
You can get something working pretty quickly if you use the Roslyn code analysis and code generation. Here’s a quick example how that could work. Note that this is somewhat fragile with detecting common properties since its based on the syntax instead of the actual semantics (making string Foo and String Foo incompatible properties). But for code that is actually generated by another code generator, this should work fine since the input should be consistent.
var input = #"
public class TestClass1
{
public string TestID { get; set; }
public string TestName { get; set; }
public string OtherTest { get; set; }
public int TestValue1 { get; set; }
public TestClass1()
{
}
}
public class TestClass2
{
public string TestID { get; set; }
public string TestName { get; set; }
public int OtherTest { get; set; }
public int TestValue2 { get; set; }
public TestClass2()
{
}
}";
// parse input
var tree = CSharpSyntaxTree.ParseText(input);
// find class declarations and look up properties
var classes = tree.GetCompilationUnitRoot().ChildNodes()
.OfType<ClassDeclarationSyntax>()
.Select(cls => (declaration: cls, properties: cls.ChildNodes().OfType<PropertyDeclarationSyntax>().ToDictionary(pd => pd.Identifier.ValueText)))
.ToList();
// find common property names
var propertySets = classes.Select(x => new HashSet<string>(x.properties.Keys));
var commonPropertyNames = propertySets.First();
foreach (var propertySet in propertySets.Skip(1))
{
commonPropertyNames.IntersectWith(propertySet);
}
// verify that the property declarations are equivalent
var commonProperties = commonPropertyNames
.Select(name => (name, prop: classes[0].properties[name]))
.Where(cp =>
{
foreach (var cls in classes)
{
// this is not really a good way since this just syntactically compares the values
if (!cls.properties[cp.name].IsEquivalentTo(cp.prop))
return false;
}
return true;
}).ToList();
// start code generation
var workspace = new AdhocWorkspace();
var syntaxGenerator = SyntaxGenerator.GetGenerator(workspace, LanguageNames.CSharp);
// create base class with common properties
var baseClassDeclaration = syntaxGenerator.ClassDeclaration("BaseClass",
accessibility: Accessibility.Public,
modifiers: DeclarationModifiers.Abstract,
members: commonProperties.Select(cp => cp.prop));
var declarations = new List<SyntaxNode> { baseClassDeclaration };
// adjust input class declarations
commonPropertyNames = new HashSet<string>(commonProperties.Select(cp => cp.name));
foreach (var cls in classes)
{
var propertiesToRemove = cls.properties.Where(prop => commonPropertyNames.Contains(prop.Key)).Select(prop => prop.Value);
var declaration = cls.declaration.RemoveNodes(propertiesToRemove, SyntaxRemoveOptions.KeepNoTrivia);
declarations.Add(syntaxGenerator.AddBaseType(declaration, syntaxGenerator.IdentifierName("BaseClass")));
}
// create output
var compilationUnit = syntaxGenerator.CompilationUnit(declarations);
using (var writer = new StringWriter())
{
compilationUnit.NormalizeWhitespace().WriteTo(writer);
Console.WriteLine(writer.ToString());
}
This would generate the following output:
public abstract class BaseClass
{
public string TestID
{
get;
set;
}
public string TestName
{
get;
set;
}
}
public class TestClass1 : BaseClass
{
public string OtherTest
{
get;
set;
}
public int TestValue1
{
get;
set;
}
public TestClass1()
{
}
}
public class TestClass2 : BaseClass
{
public int OtherTest
{
get;
set;
}
public int TestValue2
{
get;
set;
}
public TestClass2()
{
}
}
Related
I have a flat complex type which I need to map to a complex type within a list. I have achieved it using the below code but it is not elegant. The mapping for each individual item has to be specified explicitly even though the types and names match. I wanted to know if there is a more elegant way of doing this without such verbosity and tight coupling?
using AutoMapper;
MapperConfiguration _config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<FlatObject, MyDTO>()
.ForMember(dst => dst.ListObject, opt => opt.MapFrom(src => new List<ListObject> {
new ListObject {
DTOCustObject = new DTOCustObject {
MyString = src.CustType.MyString,
MyInt = src.CustType.MyInt,
MyBool = src.CustType.MyBool,
//Others...
DTOMyObject = new DTOMyObject {
SomeString = src.CustType.MyObject.SomeString
//Others...
}
}
}
}));
});
_config.AssertConfigurationIsValid();
var flatObject = new FlatObject();
flatObject.CustType.MyString = "ABC123";
flatObject.CustType.MyInt = 12345;
flatObject.CustType.MyBool = true;
flatObject.CustType.MyObject.SomeString = "Some String Content";
IMapper mapper = new Mapper(_config);
var myDTO = mapper.Map<MyDTO>(flatObject);
Console.ReadKey();
//###############
//Entity - Source
//###############
public class FlatObject
{
public CustType CustType { get; set; } = new CustType();
}
public class CustType
{
public string? MyString { get; set; }
public int MyInt { get; set; }
public bool MyBool { get; set; }
public MyObject MyObject { get; set; } = new MyObject();
}
public class MyObject
{
public string? SomeString { get; set; }
}
//#################
//DTO - Destination
//#################
public class MyDTO
{
public List<ListObject> ListObject { get; set; } = new List<ListObject>();
}
public class ListObject
{
public DTOCustObject DTOCustObject { get; set; } = new DTOCustObject();
}
public class DTOCustObject
{
public string? MyString { get; set; }
public int MyInt { get; set; }
public bool MyBool { get; set; }
public DTOMyObject DTOMyObject { get; set; } = new DTOMyObject();
}
public class DTOMyObject
{
public string? SomeString { get; set; }
}
public class MyDTO
{
public List<DTOCustObject> DTOCustObjectList{ get; set; } = new List<DTOCustObject>();
}
public class DTOCustObject
{
public string? MyString { get; set; }
public int MyInt { get; set; }
public bool MyBool { get; set; }
public DTOMyObject DTOMyObject { get; set; } = new DTOMyObject();
public DTOCustObject(ICustObjectMapper mapper){
MyString = mapper.GetMyString();
MyInt = mapper.GetMyInt();
MyBool = mapper.GetMyBool();
DTOMyObject = mapper.GetDTOMyObject();
}
}
public class DTOMyObject
{
public string? SomeString { get; set; }
public DTOMyObject(IDTOmyObjectMapper mapper)
{
SomeString = mapper.GetSomeString();
}
}
Now simply implement the Interfaces and their GetMethods on the source object, in the corresponding classes. And presto. No need for any framework of any kind.
This means, no framework, will try change syntax, and force a rewrite. You aren't locked into keeping it updated, there won't be any dependencies on it, etc.
You are free, and the time it takes you to configure, and annotate the code, is equal to the amount of time it takes you to just write the damn interfaces and implementations.
If your objects are autogenerated, simply use the partial keyword, and make the interface implementations in a partial class. Problem solved.
Something to this effect:
public class CustType : ICustObjectMapper
{
public string? MyString { get; set; }
public int MyInt { get; set; }
public bool MyBool { get; set; }
public MyObject MyObject { get; set; } = new MyObject();
string GetMyString(){
return MyString;
}
// etc for the rest of the basic types.
DTOMyObject GetMyObject(){
return new DTOMyObject(MyObject)
}
}
public class MyObject : IDTOmyObjectMapper
{
public string? SomeString { get; set; }
public string GetSomeString()
{
return SomeString;
}
}
Of course, if you don't know how to declare an interface...
public interface ICustObjectMapper {
string GetMyString();
//etc.
}
Now please, for the love of everything on this planet. STOP USING MAPPING FRAMEWORKS IN C#, IT MAKES NO SENSE!
I want to create a method that will create a List of generic objects. Is it possible? Something like this:
public class Mtrl
{
public string Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Aa { get; set; }
}
public class Trdr
{
public string Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Address { get; set; }
public string AFM { get; set; }
public string Phone01 { get; set; }
public string Aa { get; set; }
}
And then with a generic class to create my list:
public class GenericClass<T>
{
public List<T> GetData<T>()
{
List<T> myList = new List<T>();
if (typeof(T) == typeof(Trdr))
{
myList.Add(new Trdr());//Error 1: cannot convert from Trdr to 'T'
}
if (typeof(T) == typeof(Mtrl))//Error 2: cannot convert from Mtrl to 'T'
{
myList.Add(new Mtrl());
}
return myList;
}
}
My mistake. I will try to clarify more. The Classes Trdr,Mtrl etc will have many different properties. The Getdata method will take data from a web service via json and i want to create a List of Objects and return it
Something like this:
public List<T> GetData<T>()
{
List<T> myList = new List<T>();
if (typeof(T) == typeof(Trdr))
{
for (int i = 0; i < 100; i++)//fetch data from web api in json format
{
Trdr NewObj = new Trdr();
NewObj.Aa = "...";
NewObj.AFM = "...";
myList.Add(NewObj);
}
}
if (typeof(T) == typeof(Mtrl))
{
for (int i = 0; i < 100; i++)
{
Mtrl NewObj = new Mtrl();
NewObj.Aa = "...";
NewObj.Name = "name ...";
myList.Add(NewObj);
}
}
return myList;
}
}
I suggest extracting an interface (or even a base class):
//TODO: Since you have more than 2 classes, please check the common interface
public interface Idr {
string Id { get; set; }
string Name { get; set; }
string Code { get; set; }
string Aa { get; set; }
}
With all classes of interest implementing it:
public class Mtrl : Idr
{
public string Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Aa { get; set; }
}
public class Trdr : Idr
{
public string Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Aa { get; set; }
public string Address { get; set; }
public string AFM { get; set; }
public string Phone01 { get; set; }
}
Now you can use List<Idr> collection; we want the class (T) that implements Idr to have a parameterless constructor as well (new()):
public class GenericClass<T> where T : Idr, new()
{
public List<T> GetData()
{
List<T> myList = new List<T>() {
new T();
};
return myList;
}
}
Sounds like you are trying to create a new list that contains some initial data, and you need to do this for many different types T.
If Mtrl and Trdr has nothing in common and are handled completely differently, consider simply using different methods to get each type of list:
GetDataMtrl(){
var result = new List<Mtrl>();
result.Add(new Mtrl());
return result;
} // etc
Otherwise what you need is Type Constraints of Generic Parameters, that can tell the compiler more about what T is. Or rather what the different values of T must have in common. For example you can do
public List<T> GetData<T>() where T : new()
{
List<T> myList = new List<T>();
myList.Add(new T());
return myList;
}
To say that for T it has to be possible to do new T(). Then you can say GetData<Trdr>() to get a list that contains a single empty Trdr, as you code might seem to try to do.
Maybe you need to set some default values in the data. I notice the classes has a lot of variables in common. Then you might consider using inheritance to specify this commonality:
public class Mtrl
{
public string Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public string Aa { get; set; }
}
public class Trdr : Mtrl
{
public string Address { get; set; }
public string AFM { get; set; }
public string Phone01 { get; set; }
}
And then write generic code where T is either of the type Mtrl or its descendant class:
public List<T> GetData<T>() where T : Mtrl
{
List<T> myList = new List<T>();
T MtrlOrTrdr = new T();
MtrlOrTrdr.Id = "my-new-id-";
myList.Add(MtrlOrTrdr);
return myList;
}
I have a Json class "GetAllDevices()". My JSON response consists of an Array/List of objects, where each object has the below common properties.
public class GetAllDevices
{
[JsonProperty("_id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("actions")]
public Action[] Actions { get; set; }
public class Action
{
public string _id { get; set; }
public Action_Def action_def { get; set; }
}
public class Action_Def
{
public string _id { get; set; }
public string name { get; set; }
}
}
I want to create 2 generic lists containing all the above properties based on its "type".
lstfoo1 List contains all the properties(_id, name type and actions) where type="foo1". Similarly, lstfoo2 is a List which contains the above properties where type="foo2".
What I have done so far:
string strJson=getJSON();
Foo1 lstfoo1=new Foo1();
Foo2 lstfoo2=new Foo2();
List<Foo1> foo1list= lstfoo1.GetDeviceData(strJson);
List<Foo2> foo2list = lstfoo2.GetDeviceData(strJson);
public class AllFoo1: GetAllDevices
{
}
public class AllFoo2: GetAllDevices
{
}
public abstract class HomeDevices<T>
{
public string type { get; set; }
public string _id { get; set; }
public List<AllFoo1> lstfoo1{ get; set; }
public List<AllFoo2> lstfoo2{ get; set; }
public abstract List<T> GetDeviceData(string jsonResult);
}
public class Foo1: HomeDevices<AllFoo1>
{
public Foo1()
{
type = "foo1";
}
public override List<AllFoo1> GetDeviceData(string jsonResult)
{
var lst =Newtonsoft.Json.JsonConvert.DeserializeObject<List<AllFoo1>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
public class Foo2: HomeDevices<AllFoo2>
{
public Foo2()
{
type = "foo2";
}
public override List<AllFoo2> GetDeviceData(string jsonResult)
{
var lst = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AllFoo2>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
My question is, is there an easier way to do this using abstract classes? Can I directly convert my "GetAllDevices" class into an abstract class and inherit it and deserialize into it and create a generic list?
This should help, if I understand your problem correctly. Let me know if you have questions or it doesn't work as you need. I put this together really quickly without testing.
The way the Type property is defined could be improved but I left it as you had it.
public class MyApplication
{
public void DoWork()
{
string json = getJSON();
DeviceTypeOne foo1 = new DeviceTypeOne();
DeviceTypeTwo foo2 = new DeviceTypeTwo();
IList<DeviceTypeOne> foo1Results = foo1.GetDeviceData(json); // calls GetDeviceData extension method
IList<DeviceTypeTwo> foo2Results = foo2.GetDeviceData(json); // calls GetDeviceData extension method
}
}
// implemented GetDeviceData as extension method of DeviceBase, instead of the abstract method within DeviceBase,
// it's slightly cleaner than the abstract method
public static class DeviceExtensions
{
public static IList<T> GetDeviceData<T>(this T device, string jsonResult) where T : DeviceBase
{
IEnumerable<T> deviceDataList = JsonConvert.DeserializeObject<IEnumerable<T>>(jsonResult);
IEnumerable<T> resultList = deviceDataList.Where(x => x.Type.Equals(typeof(T).Name));
return resultList.ToList();
}
}
// abstract base class only used to house common properties and control Type assignment
public abstract class DeviceBase : IDeviceData
{
protected DeviceBase(string type)
{
if(string.IsNullOrEmpty(type)) { throw new ArgumentNullException(nameof(type));}
Type = type; // type's value can only be set by classes that inherit and must be set at construction time
}
[JsonProperty("_id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("type")]
public string Type { get; private set;}
[JsonProperty("actions")]
public DeviceAction[] Actions { get; set; }
}
public class DeviceTypeOne : DeviceBase
{
public DeviceTypeOne() : base(nameof(DeviceTypeOne))
{
}
}
public class DeviceTypeTwo : DeviceBase
{
public DeviceTypeTwo() : base(nameof(DeviceTypeTwo))
{
}
}
// implemented GetAllDevices class as IDeviceData interface
public interface IDeviceData
{
string Id { get; set; }
string Name { get; set; }
string Type { get; }
DeviceAction[] Actions { get; set; }
}
// renamed and relocated class Action to DeviceAction
public class DeviceAction
{
public string Id { get; set; }
public DeviceActionDefinition DeviceActionDefinition { get; set; }
}
// renamed and relocated Action_Def to DeviceActionDefinition
public class DeviceActionDefinition
{
public string Id { get; set; }
public string Name { get; set; }
}
It should be simple enough to move the implementation of method GetDeviceData() to the base class.
For this to work, you will need to add a constraint on T so the compiler knows a bit more about the base type. You will also need to implement a constructor to populate the concrete type's type string you use around. This is a necessary measure to ensure the value is always populated as it is used for comparison in the method in question:
public abstract class HomeDevices<T> where T: GetAllDevices
{
public HomeDevices(string concreteType)
{
type = concreteType;
}
public string type { get; set; }
public string _id { get; set; }
public List<AllFoo1> lstfoo1 { get; set; }
public List<AllFoo2> lstfoo2 { get; set; }
//This method is now generic and works for both.
public List<T> GetDeviceData(string jsonResult)
{
var lst = Newtonsoft.Json.JsonConvert.DeserializeObject<List<T>>(jsonResult);
var lst1 = lst.Where(x => x.Type.Equals(type)).ToList();
return lst1;
}
}
I hope that helps.
I have the following Entity-Models
public class Blog
{
public int Id { get; set;}
public string Title { get; set; }
public string Body { get; set; }
[ForeignKey("Category")]
public int? CategoryId { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Category
{
public int Id { get; set;}
public string Name { get; set; }
}
public class Comment
{
public int Id { get; set;}
public string Title { get; set; }
public string Body { get; set; }
[ForeignKey("Blog")]
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
Then I have the following view-model in which I like to tell AutoMapper to map the Blog object into the BlogViewModel notice the CategoryName property will need to come from Blog.Category.Name and each Comment in the Blog.Comments need to be converter to CommentViewModel using the organic convention.
I currently set the mapping at run time using reflection for any class that implements the ICustomMap interface. Please read the comment in the code over the Transfer(IMapper mapper) method.
public class BlogViewModel : ICustomMapFrom
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public string MyCatName { get; set; }
public IEnumerable<CommentViewModel> Comments { get; set; }
// **IMPORTANT NOTE**
// This method is called using reflection when the on Application_Start() method.
// If IMapper is the wrong Interface to pass, I can change
// the implementation of ICustomMap
// I assumed that `IMapper` is what is needed to add configuration at runtime.
public void Transfer(IConfigurationProvider config)
{
// How to I do the custom mapping for my MyCatName and Comments?
// I need to use the config to create the complex mapping
// AutoMapper.Mapper.Map(typeof(Blog), typeof(BlogViewModel));
}
}
Finally here is my CommentViewModel
public class CommentViewModel : IMapFrom<Comment>
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
How can I tell AutoMapper how to map the CategoryName and the Comments?
Updated
Here is how I would create the mapping. I would have the following 3 interfaces
public interface IMap
{
}
public interface IMapFrom<T> : IMap
{
}
public interface ICustomMapFrom : IMap
{
void Map(IConfigurationProvider config);
}
Then in the Global.cs file
I would execute the Run method on startup. Basically this method will scan assemblies and register the classes that I would want to register using the interfaces.
public class ConfigureAutoMapper
{
public void Run()
{
var types = AssemblyHelpers.GetInternalAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface && typeof(IMap).IsAssignableFrom(x))
.ToList();
RegisterStandardMappings(types);
RegisterCustomMappings(types);
}
private static void RegisterStandardMappings(IEnumerable<Type> types)
{
foreach (Type type in types)
{
if(type.IsGenericType && typeof(IMapFrom<>).IsAssignableFrom(type))
{
AutoMapper.Mapper.Map(type.GetGenericArguments()[0], type);
}
}
}
private static void RegisterCustomMappings(IEnumerable<Type> types)
{
foreach (Type type in types)
{
if (typeof(ICustomMapFrom).IsAssignableFrom(type))
{
ICustomMapFrom map = (ICustomMapFrom)Activator.CreateInstance(type);
var t = AutoMapper.Mapper.Configuration;
map.Map(Mapper.Configuration);
}
}
}
}
I wrote an NUnit test which sets up AutoMapper with your classes. AutoMapper supports the mapping of CategoryName out of the box.
[TestFixture]
public class TestClass
{
[Test]
public void Test1()
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Blog, BlogViewModel>();
});
config.AssertConfigurationIsValid();
var blog = new Blog()
{
Body = "Blog body",
Category = new Category { Name = "My Category" },
Comments = new List<Comment>() {
new Comment { Body = "Comment body 1" },
new Comment { Body = "Comment body 2" }
}
};
var mapper = config.CreateMapper();
var result = mapper.Map<Blog, BlogViewModel>(blog);
Assert.AreEqual(blog.Body, "Blog body");
Assert.AreEqual(blog.Category.Name, result.CategoryName);
List<CommentViewModel> comments = result.Comments.ToList();
Assert.That(comments.Any(c => c.Body == "Comment body 1"));
Assert.That(comments.Any(c => c.Body == "Comment body 2"));
}
}
public class Rootobject
{
public EnPickthall enpickthall { get; set; }
}
public class EnPickthall
{
public _1 _1 { get; set; }
public _2 _2 { get; set; }
public _3 _3 { get; set; }
public _4 _4 { get; set; }
/* This goes on*/
public _6236 _6236 { get; set;}
}
//For Each of the above properties a separate class has been defined:
public class _1
{
public int id { get; set; }
public int surah { get; set; }
public int ayah { get; set; }
public string verse { get; set; }
}
public class _2
{
public int id { get; set; }
public int surah { get; set; }
public int ayah { get; set; }
public string verse { get; set; }
}
/* So On for all the properties */
I got this via JSON2CSHARP!
My problem is if I employ so many properties retrieving all Verses based upon their "Surah" would be very difficult & Impractical
Here I have a book in EnPickthall class which has a separate Class for every verse. Every Verse here has it's own class.
I have been scavenging Stack Overflow for hours.Is there any way I could simplify this JSON Classes.
My Code to Creating the object model :
var serializer = new DataContractJsonSerializer(typeof(RootObject_Quran));
var result= App_Code.FileIOHelper.ReadFromDefaultFile("ms-appx:///Assets/en.pickthall.json");
var ms = new MemoryStream(Encoding.UTF8.GetBytes(result));
var data = (RootObject_Quran)serializer.ReadObject(ms);
My JSON File Link : http://globalquran.com/download/data/download.php?data_by=json&quran_by_id[]=en.pickthall
Just have a single class called Verse.
public class Verse {
public int SurahId { get; set; }
public int AyaId { get; set; }
public String Text { get; set; }
}
You don't really need a key for each verse, as the surah/aya combination is sufficient to uniquely identify a verse.
This allows for easy serialization/deserialization and also allows for easy gathering into the entire Quran again, by ordering on Surah and Aya. You could then simply use LINQ to reassemble the entire book, ordered as state above. Or it would be incredibly simple to gather passages from it also, based on a search criteria e.g. 27:18-20
Json is nested with property en.pickthall than all data wrapper again into property like id numbers so i made class and that class has Dictionary to handle data and numbers
[JsonProperty(PropertyName = "en.pickthall")]
public Dictionary picthall {get;set;}
public class VerseObject
{
[JsonProperty(PropertyName = "en.pickthall")]
public Dictionary<int, Data> picthall {get;set;}
}
public class Data
{
[JsonProperty(PropertyName = "id")]
public int id;
[JsonProperty(PropertyName = "surah")]
public int surah;
[JsonProperty(PropertyName = "ayah")]
public int ayah;
[JsonProperty(PropertyName = "verse")]
public string verse;
}
class Program
{
static void Main(string[] args)
{
List<Data> v = new List<Data>();
using (StreamReader rdr = new StreamReader(#"C:\Temp\en.pickthall.json"))
{
var str = rdr.ReadToEnd();
var jsn = JsonConvert.DeserializeObject<VerseObject>(str);
foreach(var item in jsn.picthall.Select(x=>x.Value))
{
v.Add(item);
}
Console.ReadLine();
}
}
}