I want to flag one of my methods with the StringFormatMethod attribute so Resharper syntax highlights it.
I was able to do this by referencing the JerBrains.Annotations assembly and adding the attribute.
However I find this to be a very invasive way to do this. Not everybody here uses JetBrains and it will require committing the .dll to subversion, adding the dependency and littering the code with something that is specific to a particular IDE, which I hate.
I read about the "external annotations" feature, but I wasn't able to do it. I'm not sure if I did it wrong or if it's simply not supported for a project inside the solution (i.e not a compiled assembly reference).
So is there a way to add a code annotation to a method in the project in a non-invasive way?
P.S this is the method:
using System;
namespace MyLib
{
public static class Assert
{
public static void That(bool condition, string format, params object[] #params)
{
if (!condition)
throw new Exception(string.Format(format, #params));
}
}
}
And this is the contents of
C:\Program Files (x86)\JetBrains\ReSharper\v7.1\Bin\ExternalAnnotations\MyLib.xml:
<assembley name="MyLib">
<member name="MyLib.Assert.That(System.Boolean,System.String,System.Object[])">
<attribute ctor="M:JetBrains.Annotations.StringFormatMethodAttribute.#ctor">
<argument>format</argument>
</attribute>
</member>
</assembley>
Just to sum up possibilities:
You reference nuget Jetbrains.Annotations, and DO NOT define JETBRAINS_ANNOTATIONS:
Such annotations are useful only for developers working with source code, they are not compiled in your binary (Conditional statement is used) and they are not visible when referencing your dll. You can even add developmentOnly="true" attribute to Jetbrains.Annotations in packages.config, so by default it would not be treated as dependency.
You reference as above but define JETBRAINS_ANNOTATIONS:
now you have real binary dependency and Jetbrains.Annotations.dll must be either distributed with your library or it must be downloaded as nuget dependency.
You copy annotations with internal checked (so client code would not use them), into "YourLib.Annotations": They then embedded into your lib and available for other developers even when they use only binary version.
You provide external annotations: for bigger libraries/more attributes this can also consume 40k, it is separate file, and generally it is less trivial to create/consume.
I personally went with third option (for shared libraries, projects usually just use nugets)
You don't have to reference the assembly to add annotation attributes. As per the documentation, you can go to ReSharper/Options/Code Annotations, copy the attribute implementations to the clipboard, and paste them into your own source, where ReSharper will use them. You can even change the namespace they're in if you'd prefer not to have JetBrains in your assembly.
I don't know whether you'll have any luck using external (XML) annotations for source code, though. I get the impression they're only for existing binaries. That said, I think that decorating your source with attributes is quite valuable as a source of documentation for yourself and other developers.
Don't know if it helps, but the element name <assembley> is misspelled (unless they actually used that in the schema). Should be <assembly>.
Related
I have a project that I publish as MyNuget package in a local feed. The project references a ThirdPartyNuget that has ThirdPartyExtensions public static class with public extension methods over IQueryable.
Now, in my main solution I reference MyNuget and DO NOT reference ThirdPartyNuget. Still, Visual Studio 2022 shows the extensions methods from ThirdPartyExtensions. Why?
I do not expect this as I consider ThirdPartyNuget the implementation detail of MyNuget.
The assemblies in ThirdPartyNuget are obfuscated and ThirdPartyExtensions class looks weird as it has no namespace. Here is what I see in the debugger:
typeof(ThirdPartyExtensions).Name == typeof(ThirdPartyExtensions).FullName == "ThirdPartyExtensions"
typeof(ThirdPartyExtensions).Namespace == null
typeof(ThirdPartyExtensions).GUID == {00000000-0000-0000-0000-000000000000}
What's the mechanics of this behavior?
How do I hide the visibility of ThirdPartyExtensions in my main solution?
If you use PackageReference format for your package dependencies,
PrivateAsset tag in your MyNuget .csproj may do the trick.
https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-assets
You might be using a dependency purely as a development harness and might not want to expose that to projects that will consume your package. In this scenario, you can use the PrivateAssets metadata to control this behavior.
<PackageReference Include="ThirdPartyNuget" Version="1.0.0">
<PrivateAssets>compile</PrivateAssets>
</PackageReference>
Or you can use developmentDependency in packages.config as described in this question:
Don't include dependencies from packages.config file when creating NuGet package
In terms of question: "why public dependencies is the default way?", I would say: It makes life easier.
It's easier to consume packages with public dependencies. And it's easier to make them public if it's default behavior.
For example, many packages for web development depended on Newtonsoft.json. And to configure serialization, it was needed to expose it. Another opinion about that.
Probably guys from MS have some statistics about it. But I didn't see any articles about that. They only recommend it as the default way.
In terms of your case, I'am not sure that I correctly reproduced it.
In my test I've created three projects:
One subPackage with empty default namespace.
One package with reference to SubPackage with PrivateAssets attribute.
And project, which references Package, but not references SubPackage.
It doesn't compile if I try to use extensions.
But prints '2' in runtime, if I use GetNumber method.
And if I've understood question correctly it's the desired result.
But I'm not sure, will it work for your patched ThirdPartyNuget package or not.
If you don't declare a namespace for your class, then the default global namespace is used.The global namespace is the namespace that contains namespaces and types that are not declared inside a named namespace. See here.
You can see classes which are not have namespace using global keyword. The global keyword is the global namespace alias only when it's the left-hand identifier of the :: qualifier.For more information read here
In my main solution I reference MyNuget and DO NOT reference ThirdPartyNuget. BUT your MyNuget referenced to ThirdPartyNuget. It means, your project will be referenced to ThirdPartyNuget as well.
It is not possible to hide the visibility of extensions, BUT...
Your expectation and goal is looks strange. Hovewer, you can do something like this:
If your goal is: do not allowing to use that extensions method in your projects that uses MyNuget you can create the same extensions classes with empty namespace. For example, ThirdPartyNuget project has this extension (without namespace):
public static class ThirdPartyExtensions
{
public static void DoSome(this string value)
{
//Do some
}
}
Just create the same class in MyNuget and try to use this in your project. You will get ambiguous error from compiler :).
So, it will not hide it, but it will not allow to use this extension
What is the best way to prevent C# programmer from using particular library class?
Class is from external assembly so it is impossible to use [Obsolete] attribute on it. I tried to use Resharper custom patterns but it seems not to support generics types.
Patch the library method/class (there are several plugins for Reflector) - add DeprecatedAttribute, or modify its code to throw an exception, for example.
You can also make a special unit test which runs at CI server and fails if a particular deprecated item usage indicated.
You can disassemble the library with ildasm, add [Obsolete(true)] attributes and reassemble with ilasm.
You might be able to find some assembly edit tool, like Reflexil together with a trial of Reflector.
Note that if you edit an assembly you loose all signing and stuff.
I am working on an assignment that specified "Do not use any external libraries". So I created a c# application, and the first thing I did was remove all the dll's references by default... including "System.dll".
However, I can still add this to my code:
using System;
using System.IO;
I was just curious as to how come I do not need to have System.dll as a reference in my project to do this. Thanks!
mscorlib.dll includes items in both those namespaces.
You need to right-click your project > Properties > Build > Advanced... and check "Do not reference mscorlib.dll" to remove this reference.
Different assemblies can contribute to the same namespace.
Even if you don't reference System.dll, you are still referencing (implicitly) mscorlib.dll which contributes many types to the System namespace.
These references are probably defined in your Web.config or the Machine.config file so they're included by default.
These are the default libraries.I think your question is that "Dont use third party dlls"
Another thing to consider is, if you're compiling directly through the command line, a default set of switches, including default library references, is parsed by the compiler through the default response file (csc.rsp), located in the same directory as the compiler. The fact that you are able to import namespaces from the Base Class Library without explicitly referencing them at compile time is due to the fact that their containing assemblies are included in your program by default. To change this behavior at the command line, you can use the /nostdlib switch to force it not to include mscorlib.dll, or you can use /noconfig to have it ignore the entire default response file altogether. Also, I'm not too sure what you mean by system.dll, because the namespaces you mentioned are contained within mscorlib.dll. Also, I think by "external library", your instructor must have meant any 3rd party assemblies that would assist you in solving the problem. Anything that comes included with the .NET SDK would be more of a framework library. Unless your teacher is really harsh and wants you to reinvent the wheel :P
(Yet another question from my "Clearly I'm the only idiot out here" series.)
When I need to use a class from the .NET Framework, I dutifully look up the documentation to determine the corresponding namespace and then add a "using" directive to my source code:
using System.Text.RegularExpressions;
Usually I'm good to go at this point, but sometimes Intellisense doesn't recognize the new class and the project won't build. A quick check in the Object Browser confirms that I have the right namespace. Frustration ensues.
Using HttpUtility.UrlEncode() involved adding the appropriate directive:
using System.Web;
But it also required adding a reference to .NET Framework Component for System.Web, i.e. right-click the project in Solution Explorer, select Add Reference and add System.Web from the .NET tab.
How might I discern from the documentation whether a .NET namespace is implemented by a .NET Framework Component that must be referenced? I'd rather not hunt through the available components every time I use a namespace on the off chance that a reference is needed.
(For those who like to stay after class and clean the erasers: Will Organize Usings > Remove and Sort also remove references to componenents that are not used elsewhere in the project? How do you clean up unnecessary references?)
Check out this link for UrlEncode:
Namespace: System.Web
Assembly: System.Web (in System.Web.dll)
The Assembly line tells you which dll to reference.
You'll note that the documentation (e.g. http://msdn.microsoft.com/en-us/library/system.web.httputility.aspx) tells you the name of the assembly/DLL that the class should be found in, along with the class's namespace.
Namespace: System.Web
Assembly: System.Web (in System.Web.dll)
On a side note, I know it can be a little dear, but Resharper makes things like this so much easier. If you're a serious developer, you may want to consider investing in a license. For the eraser-cleaners, Resharper adds a handy little "Find Code Dependent on Module" item to the right-click menu on references in the Solution Explorer. It's not quite an automatic cleanup, but it makes it a lot easier to see whether something's still being used by your project.
The documentation specifies two things for any type:
The namespace of the type (for the using directive)
The assembly containing the type (this is what you add a reference to)
To take an example where the two are different, look at the documentation for Enumerable:
Namespace: System.Linq
Assembly: System.Core (in System.Core.dll)
If you look at the MSDN docs, e.g.
http://msdn.microsoft.com/en-us/library/system.web.httputility.aspx
It tells you the namespace and the assembly that is required.
First, a correction to your terminology: What you are referencing is called an "assembly". An assembly contains classes that belong to a namespace. A namespace can span across multiple assemblies.
Most assemblies are named the same as the main namespace that is contained in them. For example, System.Web exists in System.Web.dll. The documentation also usually tells you which assembly needs to be referenced.
I think that you are running into a difference between c# and C here. To compare: In C, all you need to do to include a new library is to include it in the header.
It .net, you need to be aware of 2 things:
A namespace can span more than one assembly/dll (that means that you might not get a compiler error on the using clause, because some of the dlls that support that namespace are referenced -- just not the one that you need)
To "see" the contents of a given assembly, you have to add a reference to it. The using clause alone just gives you some short-cut syntax so that you can write HttpUtility.Encode(), instead of System.Web.HttpUtility.UrlEncode(), you have to add the reference in order for the compiler to "know" about the class.
To avoid your problem:
In the MSDN documents, pay attention to the assembly that the class is in, and make sure that you have a reference to the assembly.
If you browse to the MSDN for the class you're trying to use. It typically tells you the assembly that the class is in. For example the Regex class is in Assembly System (in System.dll) or the HttpUtility class is in Assembly System.Web (in System.Web.dll).
I believe tools such as ReSharper help with this, as well, and automatically references the assemblies you need.
I'm pretty sure you have to manually remove the unused references in C# projects. In VB.NET projects there's a button to list the unused references when you're in the project properties page. I don't see this in C# projects, though.
I do some stuff with XMLSerializer class. Like a most of beginners I face with performance issue on app start. I read a lot of blogs, articles and finally use SGEN tool. Now performance looks to be ok but few things are still not clear for me.
1) Should I use SGEN syntax like this:
SGen.exe /assembly:MyAssembly /type:MyRootXmlType
or it's enough to just (I use this syntax currently, I have only one Serializable class in my assembly):
SGen.exe /assembly:MyAssembly
When /type parameter can be useful in practice?
2) I read on MSDN ( http://msdn.microsoft.com/en-us/library/ee704594.aspx )
This command generates the serializer
assembly
MyAssembly.XmlSerializers.dll, which
should be added as a reference to the
current project or to the GAC.
but on all other blogs and articles (for example on SO) I read that is enough to just put MyAssembly.XmlSerializers.dll into folder where MyAssembly exists.
So what is right?
3) It's enough to just generate .XmlSerilizers.dll and deploy it together with MyAssembly or should I add something to my code yet?
I don't think so but I would like to be sure that I will not have to change my code and "magic" happens automatically.
If you don't use the /type argument for sgen.exe then it will generate de/serialization code for all public types in the assembly. Note that the [Serializable] attribute is not used in XML serialization. I doubt you'd want this, use /type to keep the generated assembly small.
Adding a reference is not necessary, Xml serialization always tries an Assembly.Load() on the .XmlSerializers.dll assembly anyway. Plus, you'll never reference the generated XmlSerializationWriterXxx and XmlSerializationReaderXxx classes directly in your code. It does have one advantage, the build system will automatically copy the assembly when you include the project in a solution.
Installing it in the GAC is only worth considering when different apps serialize and deserialize the XML file. You can provide other apps with the .XmlSerializers.dll assembly by copying the assembly by hand as well. Which is a bit error prone, use your own judgment here. Check the previous paragraph for a way to automate the copy.