I wrote a poco like this :
public class MyDirectory
{
public string Path { get; set; }
public List<MyDirectory> MyDirectories { get; set; }
}
then I wrote 2 methods like this
private static List<MyDirectory> lst = new List<MyDirectory>();
private static void DirSearch(string dir)
{
var dirs = Directory.GetDirectories(dir);
foreach (string d in dirs)
{
var ddd = new MyDirectory();
ddd.Path = d;
ddd.MyDirectories = GetList(Directory.GetDirectories(d));
lst.Add(ddd);
DirSearch(d);
}
}
private static List<MyDirectory> GetList(string[] list)
{
var lst = new List<MyDirectory>();
foreach (var l in list)
{
lst.Add(new MyDirectory() { Path = l });
}
return lst;
}
but I does not work Can anybody change it to working method ?
I dont know How fill my Poco correctly. I need recursively method.
If you want to recursively load directories then you don't GetList method. The method DirSearch is sufficient but need some refactoring like below:
private static List<MyDirectory> DirSearch(string directory)
{
var directories = new List<MyDirectory>();
foreach (var l in Directory.EnumerateDirectories(directory))
{
directories.Add(new MyDirectory
{
Path = l,
MyDirectories = DirSearch(l)
});
}
return directories;
}
Notice in the snippet I'm using Directory.EnumerateDirectories instead of Directory.GetDirectories. I do this because the latter isn't performant.
To call this method just do this:
lst = DirSearch(pathToYourDirectory);
You can make it better by using IEnumerable instead of List as type of MyDirectories property.
Your code will finally look like this :
public class MyDirectory
{
public string Path { get; set; }
public IEnumerable<MyDirectory> MyDirectories { get; set; }
}
private static IEnumerable<MyDirectory> DirSearch(string directory)
{
return Directory.EnumerateDirectories(directory).Select(l => new MyDirectory
{
Path = l,
MyDirectories = DirSearch(l)
});
}
Indeed your static property lst need to be of type IEnumerable<MyDirectory> also.
By doing those changes you will be able to start using each instance of MyDirectory instead of waiting all subdirectories to be returned when using List.
Instead of do recursive, you can use this code
Directory.GetDirectories(path, "*", SearchOption.AllDirectories)
Create cunstructor for your POCO.
public class MyDirectory
{
public MyDirectory()
{
MyDirectories = new List<MyDirectory>();
}
public string Path { get; set; }
public List<MyDirectory> MyDirectories { get; set; }
}
Recursive Method:
private MyDirectory FindRecursiveDirectories(string dir)
{
var rootDirectory = new MyDirectory();
rootDirectory.Path = dir;
foreach (var subDirectory in Directory.EnumerateDirectories(dir))
{
var myDir = FindRecursiveDirectories(subDirectory);
rootDirectory.MyDirectories.Add(myDir);
}
return rootDirectory;
}
Finally call FindRecursiveDirectories Method.
var result = FindRecursiveDirectories(yourDirectory);
Related
I can't find a solution to my problem, so I try ask here. I have a class and I want to have a method in the class to test for the state of the Properties. The method should return true if any of the properties has more one or more values assigned. But i cannot find any examples of how to loop trough all the properties of the class itself with reflection and test if Count is > than 0.
Or should I use another technique than reflection?
I just want to avoid hard coding the Properties one more time in the Test method.
using System.Reflection;
public class cP
{
public Guid gid { get; set; } = Guid.NewGuid();
public List<string> p1 { get; set; } = new List<string>();
public List<string> p2 { get; set; } = new List<string>();
public bool HasDefinedValues()
{
List<PropertyInfo> properties = this.GetType().GetProperties().ToList();
foreach (PropertyInfo property in properties)
{
if (property.PropertyType == typeof(List<int>))
{
string PName = property.Name;
if (((List<int>)property.GetValue(property.Name, null)).Count > 0) { return true; };
}
}
return false;
}
}
This is working now 😃
using System.Reflection;
public class cP
{
public Guid gid { get; set; } = Guid.NewGuid();
public List<string> p1 { get; set; } = new List<string>();
public List<string> p2 { get; set; } = new List<string>();
public bool HasDefinedValues()
{
List<PropertyInfo> properties = this.GetType().GetProperties().ToList();
foreach (PropertyInfo property in properties)
{
if (property.PropertyType == typeof(List<string>))
{
if (((List<string>)property.GetValue(this, null)).Count > 0) { return true; };
}
}
return false;
}
}
I have a class that contains Range[] as property and Range class is a self referencing class. I used [JsonIgnore] to prevent StackoverflowException but it works for only Serialize not Deserialize. How can I fix this?
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
namespace testoverflow
{
class Program
{
public static void Main(string[] args)
{
GlobalVariable.Json = "[{\"TotalBytesReceived\":0,\"Id\":\"b03750fb291a46708f8e1a7409553075\",\"NofThread\":8,\"Speed\":0,\"Progress\":0.0,\"FilePath\":\"C:\\\\Users\\\\kafeinaltor\\\\Downloads\",\"RangeDir\":\"C:\\\\Users\\\\kafeinaltor\\\\AppData\\\\Roaming\",\"Url\":\"http://ipv4.download.thinkbroadband.com/20MB.zip\",\"Ranges\":[{\"Start\":0,\"End\":9223372036854775806,\"TotalBytesReceived\":0,\"IsDownloaded\":false,\"FileId\":\"87cd7715dc0740c1b82ddd681bf2523d\",\"Size\":9223372036854775807,\"Status\":4,\"IsIdle\":false,\"SaveDir\":\"C:\\\\Users\\\\kafeinaltor\\\\AppData\\\\Roaming\",\"FilePath\":\"C:\\\\Users\\\\kafeinaltor\\\\AppData\\\\Roaming\\\\87cd7715dc0740c1b82ddd681bf2523d\",\"Md5Checksum\":null}],\"Info\":null,\"DownloadRequestMessage\":null}]";
var a = new MTDO();
Console.WriteLine(GlobalVariable.Json);
Console.ReadKey(true);
}
public static class GlobalVariable
{
public static string Json { get; set; }
}
public class MTDO
{
public MTDO()
{
Ranges = new Range[]
{
new Range(0L, 100L, ""),
new Range(101L, 200L, "")
};
Id = Guid.NewGuid().ToString("N");
Reminder.AddOrUpdate(this);
}
public string Id { get; set; }
public Range[] Ranges{ get; set; }
}
public class Range
{
public long Start { get; set; }
public long End { get; set; }
public string SaveDir { get; set; }
public long TotalBytesReceived{ get; set; }
public Range(long start, long end, string saveDir)
{
this.Start = start;
this.End = end;
this.SaveDir = Guid.NewGuid().ToString();
}
[JsonIgnore]
public Range Remaining
{
get
{
return new Range(Start + TotalBytesReceived, End, SaveDir);
}
}
}
public class Reminder
{
public Reminder()
{
}
public static void AddOrUpdate(MTDO mtdo)
{
var list = JsonConvert.DeserializeObject<List<MTDO>>(Read());
if (list == null)
list = new List<MTDO>();
var exists = list.Any(x => x.Id == mtdo.Id);
if (!exists)
list.Add(mtdo);
else
{
var i = list.Select((x, j) => new {val = x, index = j})
.First(x => x.val.Id == mtdo.Id).index;
list[i] = mtdo;
}
WriteJson(list);
}
public static List<MTDO> ReadList()
{
var list = JsonConvert.DeserializeObject<List<MTDO>>(Read());
if (list == null)
list = new List<MTDO>();
return list;
}
static string Read()
{
try
{
return GlobalVariable.Json;
}
catch
{
return "";
}
}
static void WriteJson(List<MTDO> list)
{
GlobalVariable.Json = JsonConvert.SerializeObject(list);
}
}
}
}
UPDATE: I have updated myquestion adding minimum reproducable code in Console Application. You can copy/paste and run directly.
The problem is that you have an infinite recursion:
You call MTDO constructor
Inside MTDO constructor you call Reminder.AddOrUpdate(this);
Inside that method you have var list = JsonConvert.DeserializeObject<List<MTDO>>(Read());
Which calls MTDO constructor again (step 1)
These steps keep repeating until you get StackOverflowException.
I have stored all subfolder names and it's corresponding file names(from local folder) in a class. Now I want to display it in a good way. And also need to access that files when user selects it. What is the best way to achieve it?
public class SubFolders
{
public string ItemName { get; set; }
public ObservableCollection<SubFolderFiles> SubItemsList { get; set; }
}
public class SubFolderFiles
{
public string SubItemName { get; set; }
}
Best way to show all subfolders and its files in uwp.
For this requirement, you need to create a relatively complete model like the following Illustration.
The above is recursive model, and I have make a class to match it.
public class Folder
{
public string FolderName { get; set; }
private ObservableCollection<File> _subFiles;
public ObservableCollection<File> SubFiles
{
get { return _subFiles ?? (_subFiles = new ObservableCollection<File>()); }
set
{
_subFiles = value;
}
}
private ObservableCollection<Folder> _subFolder;
public ObservableCollection<Folder> SubFolders
{
get { return _subFolder ?? (_subFolder = new ObservableCollection<Folder>()); }
set
{
_subFolder = value;
}
}
public Folder()
{
}
}
public class File
{
public string FileName { get; set; }
}
As you know, if you want to display the folders and files where in one folder on the ListView, you need to converter them into abstract listview items.
public class Item
{
public string ItemName { get; set; }
public ItemType IType { get; set; }
}
public enum ItemType
{
File,
Folder
}
Usage
FolderService.cs
public class FolderService
{
// private Folder FolderModel;
public async static Task<Folder> GetFolderInfoAsync(StorageFolder SelectFolder)
{
var FolderModel = new Folder();
FolderModel.FolderName = SelectFolder.Name;
IReadOnlyList<StorageFile> fileList = await SelectFolder?.GetFilesAsync();
foreach (StorageFile file in fileList)
{
var subFile = new File();
subFile.FileName = file.Name;
FolderModel.SubFiles.Add(subFile);
}
IReadOnlyList<StorageFolder> folderList = await SelectFolder?.GetFoldersAsync();
foreach (StorageFolder folder in folderList)
{
var subFolder = new Folder();
subFolder.FolderName = folder.Name;
FolderModel.SubFolders.Add(subFolder);
}
return FolderModel;
}
public async static Task<ObservableCollection<Item>>GetItems(StorageFolder SelectFolder)
{
var Model = await GetFolderInfoAsync(SelectFolder);
var Items = new ObservableCollection<Item>();
foreach (var file in Model.SubFiles)
{
var item = new Item
{
ItemName = file.FileName,
IType = ItemType.File
};
Items.Add(item);
}
foreach (var folder in Model.SubFolders)
{
var item = new Item
{
ItemName = folder.FolderName,
IType = ItemType.Folder
};
Items.Add(item);
}
return Items;
}
}
ManPageViewModel.cs
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
}
public Command PickCommand => new Command(() => this.BtnClick());
private async void BtnClick()
{
StorageFolder Selectfolder = ApplicationData.Current.LocalFolder;
this.Items = await FolderService.GetItems(Selectfolder);
}
private ObservableCollection<Item> _items;
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string PropertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
public ObservableCollection<Item> Items
{
get { return _items; }
set
{
_items = value;
OnPropertyChanged();
}
}
}
I am trying to save the list of data from C# code to a text file. It throws an error at foreach stating that list cannot be converted to string. Any ideas where I am going wrong?
I have to Run Application only on .Net Framework 3.5
IList<FolderDetails> ListToCheck;
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\LogFile.txt"))
{
foreach (string line in ListToCheck)
{
file.WriteLine(line);
}
}
public class FolderDetails
{
public string PropertyGroupName { get; set; }
public string ProjFiles { get; set; }
}
Examine this code:
IList<FolderDetails> ListToCheck;
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\LogFile.txt"))
{
foreach (string line in ListToCheck)
You say ListToCheck is a list of objects of type FolderDetail, but in
foreach (string line in ListToCheck)
you try to assert that the type is string instead.
Try something like
foreach (FolderDetail line in ListToCheck)
{
file.WriteLine(line.SomeAppropriatePropertyOfFolderDetail);
Rework it this way...
Add a ToString() override to your class:
private class FolderDetails
{
public string PropertyGroupName { get; set; }
public string ProjFiles { get; set; }
public override string ToString()
{
return string.Format("{0}:{1}", this.PropertyGroupName, this.ProjFiles);
}
}
Then output like this:
List<FolderDetails> foldersListToCheck = GetFolderDetails();
File.WriteAllLines(#"C:\LogFile.txt", foldersListToCheck.Select(f => f.ToString()));
IList<FolderDetails> ListToCheck;
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\LogFile.txt"))
{
foreach (string line in ListToCheck)
{
file.WriteLine(line);
}
}
In the above code ListToCheck is not a list of strings and it is not initialized
I'm creating a tree structure of a given folder (only folders no files)
also i return the security permission of each folder and add it to a list
Now how can i Loop through this composite and get all items and sub items
public abstract class FolderComponent:IEnumerable
{
public string FullName { get; set; }
public string Name { get; set; }
public List<string[]> Rules { get; set; }
public abstract void AddFolder(FolderComponent folderComponent);
public abstract IEnumerator GetEnumerator();
public abstract void AssignRules();
}
public class Folder : FolderComponent
{
public IList<FolderComponent> FolderComponents { get; set; }
public Folder(string path)
{
FullName = path;
FolderComponents = new List<FolderComponent>();
Rules = new List<string[]>();
}
public override void AddFolder(FolderComponent folderComponent)
{
FolderComponents.Add(folderComponent);
}
public override IEnumerator GetEnumerator()
{
return FolderComponents.GetEnumerator();
}
public override void AssignRules()
{
// some code
string[] rules = new string[]{"Read","Write","Execute"};
Rules.Add(rules);
}
}
public class Program
{
private static FolderComponent GetFolders(string path)
{
FolderComponent folder = new Folder(path);
folder.AssignRules();
foreach (var directory in Directory.GetDirectories(path))
{
folder.AddFolder(GetFolders(directory));
}
return folder;
}
public static void Main()
{
FolderComponent folder = GetFolders(#"C\:Test");
// How can i loop though all folder structure inside folder?
}
}
If you want to do something like this with your Folder class:
FolderComponent folders = GetFolders(#"C\:Test");
foreach (var folder in folders) { Console.WriteLine(folder.FullName); }
and get the full directory tree printed, then the GetEnumerator method needs to have logic to traverse the tree. For example
public override IEnumerator<FolderComponent> GetEnumerator()
{
// Return the current element
yield return this;
// Work through the collection of components in this folder ...
foreach (var component in FolderComponents)
{
// ... and traverse all the subfolders in each component.
// Note that this recursively calls this GetEnumerator
// method on the subfolders to work down the tree.
foreach (var subfolder in component)
{
yield return subfolder;
}
}
}
I added a method to your FolderComponent class and implement that
see if that can do the thing:
public abstract class FolderComponent : IEnumerable
{
public string FullName { get; set; }
public string Name { get; set; }
public List<string[]> Rules { get; set; }
public abstract void AddFolder(FolderComponent folderComponent);
public abstract IEnumerator GetEnumerator();
public abstract void AssignRules();
public abstract List<FolderComponent> GetAllItems();
}
public class Folder : FolderComponent
{
public IList<FolderComponent> FolderComponents { get; set; }
public Folder(string path)
{
FullName = path;
FolderComponents = new List<FolderComponent>();
Rules = new List<string[]>();
}
public override void AddFolder(FolderComponent folderComponent)
{
FolderComponents.Add(folderComponent);
}
public override IEnumerator GetEnumerator()
{
return FolderComponents.GetEnumerator();
}
public override void AssignRules()
{
// some code
string[] rules = new string[] { "Read", "Write", "Execute" };
Rules.Add(rules);
}
public override List<FolderComponent> GetAllItems()
{
var resultItems = new List<FolderComponent> {this};
foreach (var folderComponent in FolderComponents)
{
resultItems.AddRange(folderComponent.GetAllItems());
}
return resultItems;
}
}
public class Program
{
private static FolderComponent GetFolders(string path)
{
FolderComponent folder = new Folder(path);
folder.AssignRules();
foreach (var directory in Directory.GetDirectories(path))
{
folder.AddFolder(GetFolders(directory));
}
return folder;
}
public static void Main()
{
FolderComponent rootfolder = GetFolders(#"D:\4Share");
var allItems = rootfolder.GetAllItems();
foreach (var folderComponent in allItems)
{
Console.WriteLine(folderComponent.FullName);
}
Console.ReadLine();
}
you should add a list of folder type (children).
FolderComponent Parent;
List<FolderComponent> children;
And add a child when u find a folder inside specific folder. You can add parent for backward processing as well.
var directoryInfo = new DirectoryInfo(folderPath);
foreach (var directory in directoryInfo)
{
FolderComponent newSubFolder = new FolderComponent();
newSubFolder.Parent = this;
// get whatever you want like name, permissions etc.
children.Add(newSubFolder);
}
You need something like this in your code (depends on implementation)
PrintFolders()
{
foreach(var child in children)
child.PrintFolders();
Console.WriteLine(FolderName);
}