Does Linq Select does not work with IList? - linq

I'm working with Visual Studio 2019 and it suggested a conversion for a foreach to Linq which then doesn't compile:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
static void Main(string[] args)
{
var list = new List<object>();
list.Add("One");
list.Add("Two");
list.Add("Three");
// To make the point...
var iList = (IList)list;
// This doesn't compile and generates CS1061: IList does not contain a definition for Select.
// I thought Linq gave Select to list types?
var toStringList = iList.Select(s => s.ToString());
// The original foreach version:
var outputList = new List<string>();
foreach (var item in iList)
{
var itemToString = item.ToString();
outputList.Add(itemToString);
}
}

Linq is a set of extension methods on everything that implements IEnumerable<T>.
The non-generic IList doesn't implement that interface, so Linq won't work on it.
Visual Studio 2019 Professional with ReSharper doesn't suggest Select for me:

Related

Visual studio how to add custom tool/code generator configuration options

I wanted to easily turn some json schema files into classes. So googling I found NJsonSchema and I implemented this in a visual studio custom tool so I can set this on relevant json files and get my classes out. This al works and I pasted the code below. This code comes from this very answer. Though it does need a little updating for VS2022.
I find that documentation on how to do this is rather rare and the thing I am missing is how I can add something like configuration options for the custom tool.
Take for example the line "ClassStyle = CSharpClassStyle.Record," that is something one might want configurable for the user. But I cannot find anything on how to do that. Anyone have a good pointer/answer on this?
Preferably a way to add take the config from some custom properties in the file its properties that are available when the custom tool is configured on a project file.
using System;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System.Text;
using NJsonSchema.CodeGeneration.CSharp;
using NJsonSchema;
namespace ClassGeneratorForJsonSchema
{
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("GenerateClassesFromJsonSchema", "Use NJsonSchema to generate code from a json schema.", "1.0")]
[Guid("202E7E8B-557E-46CB-8A1D-3024AD68F44A")]
[ComVisible(true)]
[ProvideObject(typeof(ClassGeneratorForJsonSchema))]
[CodeGeneratorRegistration(typeof(ClassGeneratorForJsonSchema), "ClassGeneratorForJsonSchema", "{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}", GeneratesDesignTimeSource = true)]
public sealed class ClassGeneratorForJsonSchema : IVsSingleFileGenerator
{
#region IVsSingleFileGenerator Members
public int DefaultExtension(out string pbstrDefaultExtension)
{
pbstrDefaultExtension = ".cs";
return pbstrDefaultExtension.Length;
}
public int Generate(string wszInputFilePath, string bstrInputFileContents,
string wszDefaultNamespace, IntPtr[] rgbOutputFileContents,
out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
{
try
{
var schema = JsonSchema.FromJsonAsync(bstrInputFileContents).Result;
var generator = new CSharpGenerator(schema, new CSharpGeneratorSettings()
{
JsonLibrary = CSharpJsonLibrary.SystemTextJson,
ClassStyle = CSharpClassStyle.Record,
Namespace = wszDefaultNamespace
});
byte[] bytes = Encoding.UTF8.GetBytes(generator.GenerateFile());
int length = bytes.Length;
rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length);
Marshal.Copy(bytes, 0, rgbOutputFileContents[0], length);
pcbOutput = (uint)length;
}
catch (Exception ex)
{
pcbOutput = 0;
}
return VSConstants.S_OK;
}
#endregion
}
}

HtmlAgilityPack retrieve innerText without children's Innertext

I have
<p class="MyClass">
<span>Value:</span>
12345
</p>
I'd like to retrieve only 12345, if possible, thanks
Not sure if the most elegant solution, but what about
using HtmlAgilityPack;
using System;
using ScrapySharp.Extensions;
using System.Linq;
using HtmlAgilityPack.CssSelectors.NetCore;
namespace StackOverflow
{
class Program
{
static void Main(string[] args)
{
var doc = new HtmlDocument();
doc.LoadHtml(#"<p class='MyClass'>
<span>Value:</span>
12345
</p>");
//Using ScrapySharp.Extensions
var p = doc.DocumentNode.CssSelect("p")?.FirstOrDefault();
var span = p.CssSelect("span")?.FirstOrDefault();
Console.WriteLine(p.InnerText.Replace(span.InnerHtml, string.Empty)?.Trim());
//Using HtmlAgilityPack.CssSelectors.NetCore
var results = doc.QuerySelectorAll("p")?.Select(p => p.InnerText.Replace(p.QuerySelector("span").InnerHtml, string.Empty)?.Trim());
foreach(var result in results)
Console.WriteLine(result);
}
}
}
P.S.: I am used to working with ScrapySharp in conjunction to HtmlAgilityPack, but see that there is a HtmlAgilityPack.CssSelectors.NetCore that may the common choice nowadays.

Scrape a table using ScrapySharp and HtmlAgilityPack

I am trying to scrape an economic calendar from a specific website. Actually, I tried many times without any success, I don't know where I am wrong. Can you help me, pls?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HtmlAgilityPack;
using ScrapySharp.Extensions;
using ScrapySharp.Network;
namespace Calendar
{
class Program
{
static void Main(string[] args)
{
var url = "https://www.fxstreet.com/economic-calendar";
var webGet = new HtmlWeb();
if (webGet.Load(url) is HtmlDocument document)
{
var nodes = document.DocumentNode.CssSelect("#fxst-calendartable tbody").ToList();
foreach (var node in nodes)
{
// event_time
Debug.Print(node.CssSelect("div div").Single().InnerText);
// event-title
Debug.Print(node.CssSelect("div a").Single().InnerText);
}
}
Console.WriteLine("");
Console.ReadLine()
}
}
}
What error are you getting?
If you want to publish the event names and times from the website, I am assuming you need to read the table.
You can do so using
HtmlNode tablebody = doc.DocumentNode.SelectSingleNode("//table[#class='fxs_c_table']/tbody");
foreach(HtmlNode tr in tablebody.SelectNodes("./tr[#class='fxs_c_row']"))
{
Console.WriteLine("\nTableRow: ");
foreach(HtmlNode td in tr.SelectNodes("./td"))
{
Console.WriteLine(td.SelectSingleNode("./span").InnerText);
}
}
Get hold of the table with the class attribute and then use relevant XPATH to traverse the elements. Please post the error you are getting with your code.

I cannot call methods in c#

I picked up a project recently...
I cannot call methods in C #.
Did some setting in Visual Studio? I'm using Visual Studio 2012 Express.
Look my code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Web.Classes;
namespace Web.Business
{
public class TicketDB
{
Random r = new Random();
r.Next(4); // Error
}
}
You have to define a method first. Just a class is not enough.
Here is an example with a Main() method, but you can use another method (or even constructor) as well:
private static void Main()
{
Random r = new Random();
r.Next(4);
}
Your Class code should more be like that:
public class TicketDB
{
int rNum = 0;
// Constructor - called when created
public TicketDB()
{
Random r = new Random();
rNum = r.Next(4); // Error
}
}
Could. I was forgetting to call within the method. My fault.
Thanks for the help. Helped me remember the OOP.

Resolving incorrect project reference GUIDs

I have some projects in a Visual Studio solution that have ended up with project references that include the wrong GUID for the referenced project. (Possibly due to the referenced project being recreated at some stage)
eg. Consider a project CoreProject.csproj with the following properties:
<ProjectGuid>{93803F9C-8C65-4949-8D44-AB7A3D0452C8}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>CoreProject</RootNamespace>
<AssemblyName>CoreProject</AssemblyName>
Another project includes a reference to this, but at some stage the GUID has changed and is now incorrect.
<ProjectReference Include="..\CoreProject\CoreProject.csproj">
<Project>{5FD52517-79F8-41D2-B6F2-EA2D8A886549}</Project>
<Name>CoreProject</Name>
</ProjectReference>
The solution still loads and builds correctly in Visual Studio and msbuild, but I suspect having the wrong GUIDs may have some performance impact within VS.
The solution is quite large with many projects that have this issue, and I'd prefer not to have to re-add these references manually. Are there any tools or macros that can 'fix' up the project reference GUIDs?
I think a basic console app should do the trick, something like this:
using System;
using System.IO;
using System.Linq;
using Microsoft.Build.Evaluation;
public class Program
{
public static void Main(String[] args)
{
var projects = Directory.EnumerateFiles(#"...", "*.csproj", SearchOption.AllDirectories)
.Select(x =>
{
try
{
return new Project(x);
}
catch
{
return null;
}
})
.Where(x => x != null)
.ToList();
var guids = projects.ToDictionary(p => p.FullPath, p => p.GetPropertyValue("ProjectGuid"));
foreach (var project in projects)
{
var save = false;
foreach (var reference in project.GetItems("ProjectReference"))
{
var path = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(project.FullPath), reference.EvaluatedInclude));
if (!guids.ContainsKey(path))
{
Console.WriteLine("No {0}", Path.GetFileName(path));
continue;
}
var guid = guids[path];
var meta = reference.GetMetadataValue("Project");
if (meta != guid)
{
Console.WriteLine("{0} -> {1}", meta, guid);
reference.SetMetadataValue("Project", guid);
save = true;
}
}
if (save)
project.Save(project.FullPath);
}
}
}

Resources