ClosedXml.Excel HasDuplicates Extension Method Missing following Upgrade - c#

I've been tasked with taking a legacy project written with WPF, that was integrated into a bigger application and making it stand-alone. It hasn't been touched for some time, and from experience, this will always lead to issues when trying to bring the associated packages up to date. My team regularly do maintenance to keep technologies up to date, but the codebase was maintained by a different team, so they haven't followed any maintenenace schedules. I'm finding an issue with ClosedXml whereby part of our code references an extension method HasDuplicates() (found in ClosedXml.Excel) that was available in 0.74.0 but when upgrading the the latest version (0.95.4) isn't present. Searching for help isn't returning anything useful, but am sure somewhere there must be a release note that states it has been removed or renamed but I can't find it!
Using 0.74.0, this code compiles:
if (serializedPeriodAllocations.Select(o => o.Period).HasDuplicates())
{
throw new Exception("Duplicate period allocations found!");
}
But when I upgrade ClosedXml to 0.95.4 or above, it doesn't and I get the following error:
CS1061 'IEnumerable<int>' does not contain a definition for 'HasDuplicates' and no accessible extension method 'HasDuplicates' accepting a first argument of type 'IEnumerable<int>' could be found (are you missing a using directive or an assembly reference?)
Does anyone know if there is any documentation that will help me figure out why it no longer works, and if it's possible to upgrade?

After further investigation, I found an Extensions class within the project that contained a HasDuplicates extension, which was coded like this:
public static bool HasDuplicates<T>(this ICollection<T> source)
{
return source.Distinct().Count() != source.Count;
}
I added in an override for the extension that accepted IEnumerable:
public static bool HasDuplicates<T>(this IEnumerable<T> source)
{
var enumerable = source as T[] ?? source.ToArray();
return enumerable.Distinct().Count() != enumerable.Length;
}
After removing the using for ClosedXml.Excel, the HasDuplicates() doesn't return an error, as expected.

Related

System.CommandLine Command custom validator: how to search

I am writing a C# console application project (.NET 7.0) using Visual Studio for macOS 2022 v17.4 and System.CommandLine (2.0.0-beta4.22272.1).
I am trying to add a custom validator to one of my Commands, and found the following code snippet on the project's GitHub site:
this.AddValidator(commandResult =>
{
if (commandResult.Children.Contains("one") &&
commandResult.Children.Contains("two"))
{
commandResult.ErrorMessage = "Options '--one' and '--two' cannot be used together.";
}
});
However, it will not compile in my command, due to Error CS1929: 'IReadOnlyList' does not contain a definition for 'Contains' and the best extension method overload 'MemoryExtensions.Contains(ReadOnlySpan, string)' requires a receiver of type 'ReadOnlySpan' (CS1929).
I have looked for the appropriate extension method in the various System.CommandLine namespaces, but I don't see anything. (Yes, I included the System.Linq namespace.)
Can anyone suggest what is amiss?
Edit: The original code which I "borrowed" is this:
command.AddValidator(commandResult =>
{
if (commandResult.Children.Contains("one") &&
commandResult.Children.Contains("two"))
{
return "Options '--one' and '--two' cannot be used together.";
}
return null;
});
Note that this delegate returns a value, while the updated one does not, but instead sets ErrorMessage. That's one breaking change in System.CommandLine, and it's plausible that the issue here is due to another breaking change. The System.CommandLine project does note that the project is in a state of flux and subject to changes.
I have no experience with this specific library, but peeking its source hints that the collection you are calling .Contains() on doesn't contain Strings, but rather instances of SymbolResult, hence it cannot find suitable overload for the method you are trying to call.
I couldn't find the code you provided anywhere from mentioned GitHub repo, but instead found this piece of code from this test file of library:
command.Validators.Add(commandResult =>
{
if (commandResult.Children.Any(sr => sr.Symbol is IdentifierSymbol id && id.HasAlias("--one")) &&
commandResult.Children.Any(sr => sr.Symbol is IdentifierSymbol id && id.HasAlias("--two")))
{
commandResult.ErrorMessage = "Options '--one' and '--two' cannot be used together.";
}
});
The extension method you need is defined as part of the class System.Linq.Enumerable. So you need using System.Linq; at the top of your class file.
But that won't help if your project doesn't reference the assembly System.Linq.dll. (I don't know why it wouldn't, just out of the box, but perhaps it doesn't.) So you may need to add a reference for that.

DbSet not seeing LINQ definitions

To clear up the obvious first, I am:
using System.Linq;
using System.Collections.Generic;
Have a project reference to System.Core
My DbSet and DbContext classes are defined properly
The strange thing is, intellisense sees it, but I have a compiler warning and it won't compile.
I have tried cleaning the project first, restarting Visual Studio, etc and it still is complaining about:
Error CS1929 'DbSet' does not contain a definition for 'ToList' and the best extension method overload 'Enumerable.ToList(IEnumerable)' requires a receiver of type 'IEnumerable'
My "receiver" in this case is the compiler statically-determined var.
This is a new laptop and a fresh Visual Studio install ... is there something obvious I am missing here?
I wanted these internal but tried switching everything pubilc just to be sure, but I am getting the same error.
Most people report this when they are missing the using clause for Linq but I have that, and intellisense sees it which is where I am getting confused.
Line in question:
var excludedUrls = db.ExcludedUrls.ToList<string>();
I assume that in your code db is a Dbcontext with a property ExcludedUrls of type DbSet<TEntity>
DbSet<TEntity> implements IEnumerable<TEntity> If you have included LINQ, you can use the extension method Enumerable.ToList<TEntity>().
Because of your error I assume that TEntity is not a string. Your code will compile if you leave out the part:
var excludedUrls = db.ExcludedUrls.ToList();
However, this might not give a list with the elements you want. Somehow you'll have to convert each excludedUrl in your source sequence to the string representation that you want. If ToString() does not do this, you'll have to create a function yourself:
class MyDbContext : DbContext
{
public DbSet<MyTSource> ExcludedUrls {get; set;}
}
void string Transform(MyTSource excludedUrl)
{
...
}
List<string> result = dbContext.ExcludedUrls
.Select(excludedUrl => Transform(excludedUrl)
.ToList();
In words: from the sequence of excludedUrls, take each element, and transform it to a string using Transform. Convert the resulting sequence of strings to a list, which will be a list of strings
By the way, did you notice I used ToList without mentioning <string>? The compiler is able to detect the type of the elements in your input sequence, and can create a List of the same type of elements.
Consider avoiding mentioning the TSource when using the Linq functions. This has several advantages:
less typing
Easier to change the source sequence, or intermediate linq statements
Easier to detect the resulting type (and thus easier to detect the error you mentioned)
It allows the use of anonymous types
The answer, it turns out, is not calling the generic form of ToList<> here, but instead calling straight ToList(), which returns a generic List<ExcludedUrl>. A thank you to Ivan Stoev in the comments section for the tip.
I was relying too much on Intellisense hints here and not enough on memory.
As you can see, due to the way extension methods work, it presented me with a ToList in its generic form, which is why my code was written the way it was.

FizzlerEx/HtmlAgilityPack QuerySelectorAll not working

I've been attempting to set up FizzlerEx, found at http://fizzlerex.codeplex.com/. After adding the references to my project, I've attempted to run the example code given on the website- the entirety of my code is listed below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using Fizzler.Systems.HtmlAgilityPack;
namespace Fizzler_Test
{
class Program
{
static void Main(string[] args)
{
var web = new HtmlWeb();
var document = web.Load("http://example.com/page.html");
var page = document.DocumentNode;
foreach (var item in page.QuerySelectorAll("div.item"))
{
var title = item.QuerySelector("h3:not(.share)").InnerText;
var date = DateTime.Parse(item.QuerySelector("span:eq(2)").InnerText);
var description = item.QuerySelector("span:has(b)").InnerHtml;
}
}
}
However, this yields build errors, claiming that:
Error 1 'HtmlAgilityPack.HtmlNode' does not contain a definition for 'QuerySelectorAll' and no extension method 'QuerySelectorAll' accepting a first argument of type 'HtmlAgilityPack.HtmlNode' could be found (are you missing a using directive or an assembly reference?)
It would seem that QuerySelectorAll is not actually a part of HtmlNode, but given that this is the official example code taken verbatim from the website, I'd expect the creators understand how their library works. I'm at a loss as to what the actual issue could be.
A related problem seems to have been found here, but no suitable answer was ever found: Fizzler and QuerySelectorAll
It would seem that QuerySelectorAll is not actually a part of HtmlNode, but given that this is the official example code taken
verbatim from the website, I'd expect the creators understand how
their library works. I'm at a loss as to what the actual issue could
be.
You are correct about this part. Though you are not correct about the second part, since the author of HAP isn't the author of FizzlerEx. The problem is elsewhere.
Simply by looking at the error, you get the only clue you need to go to solve this .
Error 1 'HtmlAgilityPack.HtmlNode' does not contain a definition for 'QuerySelectorAll' and no extension method 'QuerySelectorAll' accepting a first argument of type 'HtmlAgilityPack.HtmlNode' could be found (are you missing a using directive or an assembly reference?)
So, what do we get; it tells us that there is no method called QuerySelectorAll in the class HtmlNode in the namespace HtmlAgilityPack. If we take a look at the source code of HAP, you can easily determine that the error message is indeed correct, since there is no method by that name in the class we are looking.
Source code for HtmlAgilityPack.HtmlNode - class
Where is this method that we want to use, but cannot find?
It's here, In the Fizzler.Systems.HtmlAgilityPack.HtmlNodeSelection-class.
After trying a few things, I get the code to work perfectly just as it is. The problem was the extensions in the reference between Fizzler and HAP source code.
If you download Fizzler you get HtmlAgilityPack at the same time. When you add the references in Visual Studio (assuming you use that), only add
Fizzler.Systems.HtmlAgilityPack.dll
HtmlAgilityPack.dll
Clean your solution and rebuild it and it should work!
You should add Fizzler by right clicking on references -> Manage Nuget Package, and search online for it, you will find it as Fizzler for HtmlAgilityPack, and then can download it.

Why can't I use the following IEnumerable<string>?

I'm getting the following error:
Error 25 The type or namespace name 'IEnumerable' could not be found (are you missing a using directive or an assembly reference?) C:\Development\Leverage\Leverage\Reports\SurveyLevel.aspx.cs 39 17 Leverage
because of this line:
private IEnumerable<string> GetDateParameters()
How do I deal with this? I tried to add in the line:
using System.IDisposable
at the top, but this doesn't fix it.
As others have said, you're missing using System.Collections.Generic;.
But that's giving you a fish; we should be teaching you to catch your own fish.
The way to solve this problem on your own is:
Enter the name of the type into your favourite search engine, and see what comes back:
IEnumerable(T) Interface (System.Collections.Generic)
http://msdn.microsoft.com/en-us/library/9eekhta0
Exposes the enumerator, which supports a simple iteration over a collection of a specified type.
See the bit that I highlighted in bold there? That's the namespace that you're missing.
If you still get the error then you are likely missing a reference; you can find out which DLL you have failed to reference by clicking on the link and reading the documentation page; it will tell you which DLL to reference.
You are missing a using System.Collections.Generic; statement at the top of the code file.
The generic IEnumerable<T> type cannot be found directly.
You could declare the full name instead:
private System.Collections.Generic.IEnumerable<string> GetDateParameters()
IEnumerable is in System.Collections
IEnumerable<T> is in System.Collections.Generic
You just need to add System.Collections.Generic namespace top of your code.
IEnumerable<T> belongs on this namespace in mscorlib.dll assembly.
You can use it like;
private System.Collections.Generic.IEnumerable<string> GetDateParameters()
Above answers are good. In my case, even after following the above answers it did not resolve the issue. Still the red squiggly constantly appeared.
Issue was the Framework of the project. It was by default set to .NET Framework 4.0.3 and changing to .NET Framework 4.0.0 will also help.
Save your Project properties after the change, build and it should all work.
Hope this helps.

Proxem's Antelope: interface not found "ISentenceSplitter"

I need to do some Natural Language Processing on various text inputs from user in a C# based desktop application. I am using Antelope for this purpose. The first step is to split the text into sentences. Following the documentation provided by Antelope, I used:
using Proxem.Antelope;
using Proxem.Antelope.Lexicon;
using Proxem.Antelope.Tools;
using Proxem.Antelope.LinkGrammar;
using Proxem.Antelope.Stanford;
using NUnit.Framework;
...
...
...
ISentenceSplitter splitter = new Tools.MIL_HtmlSentenceSplitter();
splitter.Text = text;
foreach (string sentence in splitter.Sentences)
{
// Process sentence…
}
Also, I have added references to these libraries as well. But it gives the error
The type or namespace name 'ISentenceSplitter' could not be found (are you missing a using directive or an assembly reference?) C:\Users\...
and
The type or namespace name 'Tools' could not be found (are you missing a using directive or an assembly reference?) C:\Users\...
I can't seem to figure out the solution. After a search on net I found out that other people are also having this problem but no one could actually found a solution. Can you please help me guys?
Simple answer is to avoid using this library. No offense to the authors, they might have done v.good and hard work but if it can not be utilized after all kinds of possible tries then it is useless. They mention in doc that a function belongs to a particular interface but when you go there, it doesn't exist in ANY of the available interfaces.
For those who are curious: I did contact the authors through their site but didn't get a reply even after 8 days.
There are other alternatives available like OpenNLP (java) or its C# counterpart SharpNLP.
I had the same problem. It stems from the fact that antelope dlls are compatible with
.net framework 2.0 and your application is set to use .net 4.0. (possibly)
I changed my application to .net 2.0 and trouble disappeared. :)
In addition I have used both SharpNLP and Antelope. Antelope has some superior features like
Collapse detection and port to wordnet which I had not seen in SharpNLP.
good luck.
Quite simple answer to this one: ISentenceSplitter is not in the actual release. I have v 0.8.7 which should be the same free 2009 version everyone else has To confirm this, I did a
grep -r ISentenceSplitter .
and nothing came back. Try to grep with another interface that does exist such as ILexicon and you see all the dlls that contain ILexicon.
Note that we are talking about a free version and Proxem, like other reasonable companies, want to market their technology as a profitable enterprise. Therefore you have to be happy with what you have, look into the paid solutions, use something else or write your own library which the community would be very happy to have.
I ran into that same error. Sali Hoo has the actual correct answer. This is not an answer for how to find or use ISentenceSplitter; however, it does show how Proxem's example application splits sentences as part of a larger process.
The example application that ships with the libraries can split sentences, so I figured the code allows for it. After reading a bit of code, I found that their example uses the Proxem.Antelope.Document class for sentence splitting and syntactical parsing. Rather than decompiling the libraries to see how the guts of the Document constructor uses ISentenceSplitter (I'm fairly confident that it does) I just used the class and it actually ended up performing all of the functions I needed, not just sentence splitting. I definitely recommend taking a look at how their example uses it, but here's the essence of my implementation:
public sealed class SyntaxService : ISyntaxService
{
public SyntaxService(IParser parser, ILexicon lexicon)
{
m_parser = parser;
m_lexicon = lexicon;
// These are the setting I needed, YMMV. They seem to add a lot of UI logic to this method :(
m_processingResources = new ProcessingResources(m_lexicon, null, null, m_parser, 5, null, false, null, null, null, null, false);
}
public IEnumerable<Sentence> GetSentences(string s)
{
IDocument document = new Document(s, m_processingResources);
return document.Select(Mappers.SentenceMapper.Map);
}
readonly IParser m_parser;
readonly ILexicon m_lexicon;
readonly IProcessingResources m_processingResources;
}
The Sentence class referenced here is a simplified syntax tree along with the original sentence value. If you're not super interested in this type of dependency injection friendly wrapping and mapping, you can just use the guts of GetSentences(string).

Categories