I am using PostSharp in an Outlook Plugin app. If I add the following attribute to a class in my project it logs properly:
namespace Foo.Bar
{
[Log(AttributeTargetMemberAttributes = MulticastAttributes.Public)]
public class FooBar {...}
}
What I really want to do is log everything in the Foo.* namespace. I tried using the addin in VS which created a globalaspects.cs and updated my project.pssln file. At this point it wont build with the following error msg:
.dll uses non-licensed features (PostSharp Professional). Please enter a valid license key.
I figured it was recursing on itself so I added an AttributeExclude = true in the assembly line that was generated for me. It now looks like this (in globalaspects.cs):
[assembly: Log(AttributeExclude = true, AttributeTargetTypes = "Foo.*", AttributeTargetTypeAttributes = MulticastAttributes.Public, AttributeTargetMemberAttributes = MulticastAttributes.Public)]
No luck, it doesn't log anything this way. Any ideas why?
Additional info:
I am logging to log4net and I have other logging code that is working (it also works at both the class and method levels with PostSharp).
According to this page free license of PostSharp currently has limitation on number of methods on which [Log] attribute is applied. In my opinion, you have exceeded this number by applying the aspect on the whole namespace.
AttributeExclude means that the attribute will not be applied on declarations that satisfy conditions set in this attribute. It is basically set inclusion/exclusion operation. For example you can include Namespace1, exclude Namespace1.Namespace2 and again include Namespace1.Namespace2.Namespace3.
Therefore the following would be correct:
[assembly: Log(AttributeTargetTypes = "Foo.*",
AttributeTargetTypeAttributes = MulticastAttributes.Public,
AttributeTargetMemberAttributes = MulticastAttributes.Public)]
For more information about attribute multicasting, you can take a look on this article.
Note to reviewers: I'm one of developers working on PostSharp. I'm aware that this answer touches licensing, which is behind the red line and I have tried my best not to cross it too much.
Related
My Goal
My team decided, that they wanted to incorporate automation to enforce coding guidelines in .razor files.
Since we're already using StyleCopAnalyzers, I might implement our own Analyzer to achieve this goal.
Example
To better make you understand what's in my mind, consider the following example.
Let the following be valid code:
<MyGrid>
<MyItem></MyItem>
<MyItem></MyItem>
<MyItem></MyItem>
</MyGrid>
Now, If someone wouldn't encapsulate <MyItem> within <MyGrid> it would cause the Analyzer to report a diagnostic like "MyItem should be direct child of a MyGrid".
What I tried
Firstly, I followed microsoft's tutorial: Write your first analyzer and code fix. This worked perfectly well.
However, my next step was to create a Sample Blazor WASM Application using the default template. When I executed the MakeConstAnalyzer on the Sample Blazor Application, I'd get the following behavior.
Modifying Program.cs like this:
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
// I get squiggly lines here with the expected analyzer message from the MakeConstAnalyzer
int bla = 0;
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
}
}
But modifying Counter.razor like this:
private void IncrementCount()
{
int bla = 0; // add this line
currentCount++;
}
now, this won't show the analyzers message. Of course this will
trigger a compiler warning, but mainly this tells me, that for some
reason the Analyzer isn't executed on the Counter.razor file.
The Microsoft.CodeAnalysis.Razor Package
I thought, I'd mention it here. I found it on Nuget and tried to integrate it in the sample.
Caution
I have no clue, If the purpose of the package is even remotely connected, to what I want to achieve, since I really didn't find any documentation.
Since the microsoft tutorial clearly states, that any Analyzer must in some way inherit DiagnosticAnalyzer, I also checked the package for an implementation. But in both, the Microsoft.CodeAnalysis.Razor and Microsoft.AspNetCore.Razor.Language Package there is no class, that inherits from DiagnosticAnalyzer.
I've also tried to decorate my Analyzer, to specify, that it should also parse *.razor files, like that:
[DiagnosticAnalyzer(LanguageNames.CSharp, Microsoft.CodeAnalysis.Razor.RazorLanguage.Name)]
Summary
At this point, I don't know, what else to try. Also I didn't find anything remotely like that in the web.
These are my Questions:
How can I instruct my Analyzer to also parse .razor files?
Also how would I access the razor code in that approach?
I can imagine to either use Analyzers Syntax to traverse the Component Tree, but I think I could realize most of my usecases by only having the plain unparsed code.
I'm usually a javascript developer, but for my company I just started learning c# in order to use the CimatronE 13 API to develop custom command line PDM tools for this 3D modelling software.
As I'm making progress understanding the programming language, there's this frustrating situation where I want to use an API endpoint method but I can't manage to get it working.
The Cimatron documentation says the following:
IPdm::GetRelatedDocuments
Syntax: RelatedDocuments = GetRelatedDocuments ( DocumentPath );
This method allows you to get related files from compound types of files, for example Assembly or Drawing.
Input: (String) DocumentPath,
Path to file. For example \Documents\Location\Folder\Document. The file must be Assembly or Drawing.
Return: (Variant) RelatedDocuments,
Variant type array each element of which contain two dimensioned string type array of files related to selected one.
This looks pretty straight forward to me, so I tried calling it in multiple ways from within the static void Main() method, but I keep getting errors:
var RelatedDocuments = interop.CimBaseAPI.IPdm.GetRelatedDocuments("path");
CS0120: An object reference is required for the non-static field, method, or property 'IPdm.GetRelatedDocuments(string)'
interop.CimBaseAPI.IPdm pdm = new interop.CimBaseAPI.IPdm();
var RelatedDocuments = pdm.GetRelatedDocuments("path");
CS0144: Cannot create an instance of the abstract class or interface 'IPdm'
Any ideas? It's probably simple but I'm still a noob with c# :p
EDIT:
Cimatron documentation about the interface interop.CimBaseAPI.IPdm:
Properties:
Get
Query (String, DocumentEnumType, DocumentEnumUnit )
Variant
Methods:
A lot, including Variant GetRelatedDocuments ( String )
As how I see it now... interop.CimatronE.IPdm is an interface and in order to use it's methods, we first need access to the Cimatron application. Using the application object, we can use it's methods to get the desired interfaces such as IPdm and use their methods.
The following code gives no errors from the compiler but does when executing. This seems to be related to version 13 of CimatronE, since the application object works just fine using version 12. A lot has changed between these versions which I think is the reason the API is not functioning properly, outdated.
interop.CimAppAccess.AppAccess AppAcc = new interop.CimAppAccess.AppAccess();
interop.CimatronE.IApplication CimApp = /*(interop.CimatronE.IApplication)*/AppAcc.GetApplication();
interop.CimatronE.IPdm pdm = CimApp.GetPdm();
var RelatedDocuments = pdm.GetRelatedDocuments("path");
Console.WriteLine(RelatedDocuments);
Please correct me if I'm wrong! (since I just started and still learning c#)
I ran into this same issue with Cimatron 14.
I needed to make some changes in Visual Studio for things run properly with Cimatron.
Run Visual Studio in administrator mode
Set your Debug & Release Solution Platform to 'x64'
It was also recommended to point the build path for release & debug to the same folder as the Cimatron references. In my case 'C:\Program Files\3D Systems\Cimatron\14.0\Program'. However my code appears to run fine without this.
I created the Cimatron Application with this code (VB.Net):
Dim gAppAccess As New CIMAPPACCESSLib.AppAccess 'Define an AppAccess object to get running active application
Dim gApp As CIMAPPACCESSLib.Application 'Define an Application object
gApp = gAppAccess.GetApplication 'Getting running active application
If gApp Is Nothing Then
gApp = New CIMAPPACCESSLib.Application 'Creating a new instance of a Cimatron application
End If
References: Interop.CIMAPPACCESSLib.dll & interop.CimServicesAPI.dll
It is my understanding that Cimatron 15 may also requires some manifest changes.
There is some help information in the Cimatron program under Cimatrom Modules > Cimaton SDK that may be mildly helpful.
So I am developing a Roslyn-based frontend compiler that parses a C# solution, performs rewriting on the syntax trees to desugar some constructs of my DSL, and then uses the Roslyn APIs to compile and emit executables/dlls. This last part, given a compilation, is done very simply like this (some details omitted for clarity):
var compilation = project.GetCompilationAsync().Result;
var compilationOptions = new CSharpCompilationOptions(outputKind,
compilation.Options.ModuleName, compilation.Options.MainTypeName,
compilation.Options.ScriptClassName, null,
compilation.Options.OptimizationLevel, compilation.Options.CheckOverflow,
false, compilation.Options.CryptoKeyContainer,
compilation.Options.CryptoKeyFile, compilation.Options.CryptoPublicKey,
compilation.Options.DelaySign, Platform.AnyCpu,
compilation.Options.GeneralDiagnosticOption,
compilation.Options.WarningLevel,
compilation.Options.SpecificDiagnosticOptions,
compilation.Options.ConcurrentBuild,
compilation.Options.XmlReferenceResolver,
compilation.Options.SourceReferenceResolver,
compilation.Options.MetadataReferenceResolver,
compilation.Options.AssemblyIdentityComparer,
compilation.Options.StrongNameProvider);
var targetCompilation = CSharpCompilation.Create(assemblyFileName,
compilation.SyntaxTrees, compilation.References,
compilationOptions);
EmitResult emitResult = null;
using (var outputFile = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
emitResult = targetCompilation.Emit(outputFile);
if (emitResult.Success)
{
return fileName;
}
}
So everything works perfectly fine, until I tried to compile a solution where a project A declares some internal classes/fields, and then uses the [assembly: InternalsVisibleTo("...")] attribute (in the AssemblyInfo.cs file) to give visibility of these internals to another project B.
Directly compiling using visual studio works perfectly fine and allows B to see these internal declarations of A. However, when I try to compile through my tool using the Roslyn APIs, it is like the InternalsVisibleTo attribute is completely ignored, and I am getting back errors, such as:
error CS0122: ... is inaccessible due to its protection level
Which means the InternalsVisibleTo was not picked up.
I was expecting that Roslyn would automatically pick this up from the parsed project info, but I am now wondering if I have to enable some specific compilation option or to add some information manually?
I have looked around but I cannot find a similar question or an answer, unless I am missing something. I can give some more information if required. Thanks!
InternalsVisibleTo requires matching the public key used for signing the other assembly exactly (or no public key in case of unsigned assembly).
Double check you are providing either that correct key and the correct assembly name including the namespace.
Particularly, here, you are interested to the full public key, and not the public key token.
For more information and how to extract the public key for this purpose, please have a look at InternalsVisibleToAttribute Class.
I'm currently trying to load and use the Gephi Toolkit from within a .Net 4 C# website.
I have a version of the toolkit jar file compiled against the IKVM virtual machine, which works as expected from a command line application using the following code:
var controller = (ProjectController)Lookup.getDefault().lookup(typeof(ProjectController));
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
The three instances are correctly instantiated in a form similar to org.gephi.project.impl.ProjectControllerImpl#8ddb93.
If however I run the exact same code, with the exact same using statements & references, the very first line loading the ProjectController instance returns null.
I have tried a couple of solutions
Firstly, I have tried ignoring the Lookup.getDefault().lookup(type) call, instead trying to create my own instances:
var controller = new ProjectControllerImpl();
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
This fails at the line controller.newProject();, I think because internally (using reflector) the same Lookup.getDefault().lookup(type) is used in a constructor, returns null and then throws an exception.
Secondly, from here: Lookup in Jython (and Gephi) I have tried to set the %CLASSPATH% to the location of both the toolkit JAR and DLL files.
Is there a reason why the Lookup.getDefault().lookup(type) would not work in a web environment? I'm not a Java developer, so I am a bit out of my depth with the Java side of this.
I would have thought it possible to create all of the instances myself, but haven't been able to find a way to do so.
I also cannot find a way of seeing why the ProjectController load returned null. No exception is thrown, and unless I'm being very dumb, there doesn't appear to be a method to see the result of the attempted load.
Update - Answer
Based on the answer from Jeroen Frijters, I resolved the issue like this:
public class Global : System.Web.HttpApplication
{
public Global()
{
var assembly = Assembly.LoadFrom(Path.Combine(root, "gephi-toolkit.dll"));
var acl = new AssemblyClassLoader(assembly);
java.lang.Thread.currentThread().setContextClassLoader(new MySystemClassLoader(acl));
}
}
internal class MySystemClassLoader : ClassLoader
{
public MySystemClassLoader(ClassLoader parent)
: base(new AppDomainAssemblyClassLoader(typeof(MySystemClassLoader).Assembly))
{ }
}
The code ikvm.runtime.Startup.addBootClassPathAssemby() didn't seem to work for me, but from the provided link, I was able to find a solution that seems to work in all instances.
This is a Java class loader issue. In a command line app your main executable functions as the system class loader and knows how to load assembly dependencies, but in a web process there is no main executable so that system class loader doesn't know how to load anything useful.
One of the solutions is to call ikvm.runtime.Startup.addBootClassPathAssemby() to add the relevant assemblies to the boot class loader.
For more on IKVM class loading issues see http://sourceforge.net/apps/mediawiki/ikvm/index.php?title=ClassLoader
I'm using StyleCop and want to suppress some warning which does not suit my style. I prefer to have solution for
1) in-line code suppressing
2) global setting suppressing
I've searched the internet but still not sure how to do the suppressing.
For method 1), They said to add the lines:
[assembly: SuppressMessage("Microsoft.Design",
"SA1202:All private methods must be placed after all public methods",
Scope = "namespace", Target = "Consus.Client.ClientVaultModule.Services.OnlineDetection")]
But they do not say where and which namespace to be used.
For method 2), they said to use GlobalSuppress file but it seems not easy to search for a how-to do it at the moment.
Please help.
[Edited]
In my case, I have the warning about SA1202: All private methods must be placed after all public methods which is bothering since I group my related codes into regions. I want to suppress those warning for just some certain methods.
Here's what you need:
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess")]
An example of inline suppression would be similar to this - examine the namespaces in the code compared to the suppression
namespace Soapi
{
///<summary>
///</summary>
///<param name = "message"></param>
///<param name = "statusCode"></param>
///<param name = "innerException"></param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)")]
public ApiException(string message, ErrorCode statusCode, Exception innerException)
: base(String.Format("{0}\r\nStatusCode:{1}", message, statusCode), innerException)
{
this.statusCode = statusCode;
}
A global supression file is a file in the root of your project named GlobalSuppressions.cs and might look like this:
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Error List, point to "Suppress Message(s)", and click
// "In Project Suppression File".
// You do not need to add suppressions to this file manually.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Soapi.ApiException.#.ctor(System.String,Soapi.ErrorCode,System.String,System.Exception)")]
And you can generate this code automatically by right-clicking on the warning.
Starting with StyleCop 4.3.2, it is possible to suppress the reporting of rule violations by adding suppression attributes within the source code.
Rule Suppressions
http://stylecop.soyuz5.com/Suppressions.html
but it says -
Global Suppressions
StyleCop does not support the notion of global suppressions or
file-level suppressions. Suppressions must be placed on a code
element.
If you've installed StyleCop, you can right-click your project and there will be a StyleCop option. Click this and you'll see you can prevent certain rules from even running against your project. Moreover, you can create a separate rules file to share between different projects. This means you can configure the rules once the way you want them and then share that configuration between all your projects.
For individual overrides, SuppressMessage is the way to go.
Go to Solution Explorer
Go to your project
Expand references
Expand Analyzers
Expand StyleCop.Analyzers
Right click on a particular rule which you want to disable at a global (project) level
Set Rule Set severity -> Select None
Read the admonition from Style Cop, looking for the alphanumeric code. In your case 'SA1202'. Then browse to the corresponding page on the Style Cop website. Change the URL as appropriate https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md
Copy the line labelled 'How to Suppress Violations'. Paste the attribute above the class about which Style Cop moans
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed.")]
Cant you just remove the rule instead of soiling your code?
Same goes for FxCop...
1.
In your case, correct SuppressMessage attribute should like like the following:
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess")]
private void SomeMethod()
{
}
Note that you can place it on any other element (e.g, on the class - then all similar violations in the entire class will be supressed).
I also agree that it's quite unobvious what to write in these fields.
Actually, the first one should be the fully qualified name of StyleCop analyser class and could be found from the source code (e.g. from here).
The second one should start with rule code, then colon and the name of the rule enumeration (luckily, it always looks like the rule name displayed in the Settings Editor, but with no whitespaces).
2.
Regarding suppressing rules "globally" - why don't just turn them off via Settings Editor? Settings files are inherited through the file system, so you could easily have one "main" settings file at the "top" of your folder structure, and some other files (holding the "difference" from main) with exceptions made for some projects, if you want so (like described here).
Good luck!
You can disable the rules you don't want in Settings.StyleCop file, which is in the project root folder.
You will need the namespace that contains the rule, which can be found here:
http://stylecop.soyuz5.com/StyleCop%20Rules.html
Settings.stylecop file code for your reference:
<StyleCopSettings Version="105">
<Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
<Rules>
<Rule Name="ElementsMustBeSeparatedByBlankLine">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
</Analyzers>
</StyleCopSettings>
Alternatively you could move the code in regions into partial classes. Then the issue with the stylecop rule will go away.
In addition to the helpful answers already in place:
If you suppress a warning in the suppression file GlobalSuppressions.cs,
you can edit that [assembly: SuppressMessage(StyleCop...blabla line and entirely remove the Scope=... and Target=... tags. That makes the suppression global in the project.
The README.md for the StyleCop.Analyzers NuGet package used by Visual Studio 2015+ contains a link to the documentation for the rules. The documentation for each rule contains a "How to suppress violations" section. For the SA1202 rule, the options are:
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed.")]
and
#pragma warning disable SA1202 // ElementsMustBeOrderedByAccess
#pragma warning restore SA1202 // ElementsMustBeOrderedByAccess