Disable auto-generation of [Serializable] attribute by VS2015 C# compiler - c#

VS2015 C# compiler emits [Serializable, CompilerGenerated] attributes on all auto-generated helper classes for LINQ queries. Prior versions of Visual Studio used to emit only [CompilerGenerated] attribute on such classes.
Is there a way to disable auto-generation of [Serializable] attribute in VS2015? The reason is that our obfuscator refuses to rename classes marked as [Serializable], although in our case it is 100% safe because we don't use serialization.
Here is the example of auto code generated by older compilers:
[CompilerGenerated]
private sealed class <>c
{
public static readonly Program.<>c <>9 = new Program.<>c();
// ... more stuff here
}
Here is what VS2015 emits:
[Serializable, CompilerGenerated]
private sealed class <>c
{
public static readonly Program.<>c <>9 = new Program.<>c();
// ... more stuff here
}
I want the compiler to stop generating that [Serializable] attribute. Is it possible?

I hesitated to post this... maybe i'm wrong, but i'm sure this can lead to the right direction.
So Roslyn is the compiler which generates the code (that's the default compiler in VS2015), and it's open source (see here). The LabdaRewriter.cs (here) contains the logic which rewrites the lambda into the class and does all the magic. In the GetStaticFrame method there is this line:
_lazyStaticLambdaFrame = new LambdaFrame(_topLevelMethod, scopeSyntaxOpt: null, methodId: methodId, closureId: closureId);
Now LamdaFrame is the class which represents the generated class (see here) (in your case <>c which gets the SerializableAttribute).
Remember the scopeSyntaxOpt: null part from the constructor parameter!
Here is the constructor:
internal LambdaFrame(MethodSymbol topLevelMethod, CSharpSyntaxNode scopeSyntaxOpt, DebugId methodId, DebugId closureId)
: base(MakeName(scopeSyntaxOpt, methodId, closureId), topLevelMethod)
{
_topLevelMethod = topLevelMethod;
_constructor = new LambdaFrameConstructor(this);
this.ClosureOrdinal = closureId.Ordinal;
// static lambdas technically have the class scope so the scope syntax is null
if (scopeSyntaxOpt == null)
{
_staticConstructor = new SynthesizedStaticConstructor(this);
var cacheVariableName = GeneratedNames.MakeCachedFrameInstanceFieldName();
_singletonCache = new SynthesizedLambdaCacheFieldSymbol(this, this, cacheVariableName, topLevelMethod, isReadOnly: true, isStatic: true);
}
...
}
And there is one property called IsSerializable:
// display classes for static lambdas do not have any data and can be serialized.
internal override bool IsSerializable
{
get { return (object)_singletonCache != null; }
}
As you see in the constructor this _singletonCache is basically never null when the instance is created in the GetStaticFrame method (I think this is the case where you do not capture values from the outside in you LINQ expression (FIXME)) , therefore it returns true, and I think based on this property the generated class get's the SerializableAttribute.
So I think at the moment this is hard-coded and you cannot change this, unless you touch the Roslyn source code and improve this....

I ended up writing a simple dnlib-based tool that parses compiled assembly and changes the Serialized property of every class with the [CompilerGenerated] attribute to false. Seems to work well enough for my needs.

Related

Making extension methods from a third party library obsolete

This question is not about a method I can mark with [System.Obsolete]. The method I wanna ignore is in a dll I don't have control over.
I use a 3rd party library which contains an extension method for objects. This leads to confusion and may cause problems in the future.
Is there any way to mark this extension method (or all the extension methods from a certain dll ) as obsolete externally or prevent this extension method appearing in intellisense. The problematic method is :
public static class ExtensionMethods
{
public static bool IsNumeric(this object obj)
{
if (obj == null)
return false;
return obj.GetType().IsPrimitive || obj is double || (obj is Decimal || obj is DateTime) || obj is TimeSpan;
}
}
You can do this with a Roslyn Code Analyzer. The following code will create a DiagnosticAnalyzer that will give a compiler warning if String.EndsWith() is used.
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class ForbiddenMethodsAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor("Forbidden",
"Don't use this method!",
"Use of the '{0}' method is not allowed",
"Forbidden.Stuff",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "This method is forbidden");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression);
}
private static void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context)
{
var invocationExpression = (InvocationExpressionSyntax)context.Node;
var memberAccessExpression = invocationExpression.Expression as MemberAccessExpressionSyntax;
if (memberAccessExpression?.Name.ToString() == "EndsWith")
{
var memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccessExpression).Symbol as IMethodSymbol;
var containingType = memberSymbol.ContainingType;
if (containingType.ContainingNamespace.Name == "System" && containingType.Name == "String")
{
var diagnostic = Diagnostic.Create(Rule, invocationExpression.GetLocation(), memberAccessExpression.ToString());
context.ReportDiagnostic(diagnostic);
}
}
}
}
There are 3 options to use an Analyzer like this:
Add the DiagnosticAnalyzer code directly to your project. It will apply only to that solution.
Create a
class library with the DiagnosticAnalyzer in it, and distribute it
as a Nuget package. It will apply only to solutions that use the package.
Compile a full VSIX extension containing the
class. The analyzer will work on any solution you load.
This is the first project I've done that uses the Roslyn Code Analysis functionality, so unfortunately I don't understand everything that is going on here. I started with the default Analyzer template and tried various methods, stepped through code, and looked at variables with the watch windows until I found the information I needed for this functionality.
The basic process is to register a SyntaxNode Analysis function, filtered to expressions that invoke a method. Within that method I check to see if the Name of the MemberAccessExpressionSyntax being examined is "EndsWith". If it is, I get the ContainingType that the method is on, and check to see if it is on the String class in the System namespace. If it is, I create a Diagnostic instance from a DiagnosticDescriptor to tell the IDE where the problem is, and how much of a problem it represents (A warning in this case, I could make it a full Error if I wanted, which would prevent the code from compiling). It is also possible to present the user with different options to automatically fix the error, but I haven't explored that yet.
A lot of the information came from this tutorial, as well as a whole lot of trial and error.
The best way to handle this would be to use Roslyn and create your own code analyzer, or use an existing tool like FxCop.
However, I found a very non-elegant workaround for this.
In your project you can create a class with the same name as the referenced class, residing in an identical namespace, with the exact same method. Now mark your method as obsolete.
The below code sample has a reference to a library with an ExtensionMethods class which is defined in the External namespace. In the line marked with (*) comment, where the method is called using the static method call syntax, the compiler warns you that the type ExtensionMethods conflicts with an imported type. It also tells you that the method is obsolete (since you have shadowed the imported type, it sees your definition). So when you invoke the method, your code will run. In the line marked with (**) comment, where the method is called using the extension method call syntax, the compiler says that the call is ambiguous and the code won't compile. The only workaround I know of is to turn this call into line (*), which will produce the obsolete warning.
With this solution you will be able to call other extension methods from the referenced type if you use the extension method syntax, provided you don't have the same method defined in your class.
using System;
using External;
namespace Internal
{
class Program
{
static void Main(string[] args)
{
ExtensionMethods.IsNumeric(new object()); // (*)
new object().IsNumeric(); // (**)
}
}
}
namespace External
{
public static class ExtensionMethods
{
[Obsolete]
public static bool IsNumeric(this object o)
{
if (obj == null)
return false;
return obj.GetType().IsPrimitive || obj is double || (obj is Decimal || obj is DateTime) || obj is TimeSpan;
}
}
}

Generating and serialising metadata at compile time using PostSharp

I'm trying to do something which I feel should be straight forward and simple to do, yet for the life of me, I can't get it to work. Using PostSharp, I want to create an aspect that I apply to a class (or interface) definition and that aspect, at compile time, reflects the type that it has been applied to and then stores that reflection information in a variable ready for extraction at run time.
I know that the CompileTimeInitialize function should be used to generate the reflection information and save it to a variable. This all then gets serialised. However, I can't get the information stored out at run time. The RuntimeInitialize can see the variable and the data in it, but when I then get the attribute from the type elsewhere in my code using GetCustomAttributes, the attribute is empty.
Here is some of the code I have so far:
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Class, AllowMultiple = false, PersistMetaData = true)]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class MetadataAttribute : TypeLevelAspect {
public MetadataAttribute() { }
private int test;
public override bool CompileTimeValidate(Type type) {
this.test = 11;
return true;
}
public override void CompileTimeInitialize(Type type, AspectInfo aspectInfo) {
this.test = 9;
}
public override void RuntimeInitialize(Type type) {
// When I break here, I can see during debugging, that test is 11 (I would have expected 9 to be honest, but I suspect that CompileTimeInitialize is not executed for a TypeLevelAspect - unless I am mistaken?)
}
}
Here is the console application that I am trying to use to extract the number:
class Program {
static void Main(string[] args) {
var ma = typeof(Test).GetCustomAttribute<MetadataAttribute>();
var test = new Test();
var ma2 = test.GetType().GetCustomAttribute<MetadataAttribute>();
// When I break here, both ma and ma2 have test set to 0.
}
}
[Metadata]
public class Test { }
Thanks in advance for any help, it is much appreciated and goes a long way to making my hair last longer on my head than in my hands :)
When you are using Type.GetCustomAttributes, you are requiring the CLR to build a new instance of custom attributes from their definition stored in metadata, i.e. by calling the constructor and setting fields and properties. Therefore, you are not getting the instance that PostSharp created and initialized, but a fully new instance.
If you want to access the PostSharp instance, you should use RuntimeInitialize to store this instance in some kind of shared repository of aspect instances, then access them from code. Note that PostSharp runs RuntimeInitialize lazily, so you won't be able to access your instance until it has been initialized.

Order of initialization of static parameters

Few weeks ago, I switched from Java to C#. Today, I had a weird behavior and I try to reproduce it in this simple sample. I'm using a .net FW 4.
I have three classes:
First, the abstract one:
namespace ReadonlyStaticOrder
{
using System;
using System.Collections.Generic;
public abstract class AbstractClass
{
public AbstractClass(string value, IEnumerable<string> someValues)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (someValues == null)
{
throw new ArgumentNullException("someValues");
}
// would do something after...
}
}
}
The second one :
namespace ReadonlyStaticOrder
{
using System.Collections.Generic;
public sealed class ReadonlyOrderInitialization : AbstractClass
{
// this line introduces the bug, since it call the ctor before SomeValues already initialized
// if removed, no more exception
public static readonly ReadonlyOrderInitialization Sample = new ReadonlyOrderInitialization("sample");
private static readonly IEnumerable<string> SomeValues = new string[] { "one", "two", "three" };
public ReadonlyOrderInitialization(string value)
: base(value, SomeValues)
{
}
}
}
And the demonstrator:
namespace ReadonlyStaticOrder
{
using System;
public sealed class Program
{
static void Main(string[] args)
{
try
{
new ReadonlyOrderInitialization("test");
}
catch (TypeInitializationException typeInitializationException)
{
Console.WriteLine(typeInitializationException.Message);
Console.WriteLine(typeInitializationException.InnerException.Message);
Console.WriteLine(typeInitializationException.StackTrace);
}
Console.ReadLine();
}
}
}
And the output is:
The type initializer for
'ReadonlyStaticOrder.ReadonlyOrderInitialization' threw an exception.
Value cannot be null. Parameter name: someValues at
ReadonlyStaticOrder.ReadonlyOrderInitialization..ctor(String value)
at ReadonlyStaticOrder.Program.Main(String[] args) in
d:\stackoverflow\static
readonlyissue\ConsoleApplication1\ReadonlyStaticOrder\Program.cs:line
12
I added a comment on the line which introduces the bug. For me, the compiler would have to warn me that the behavior can be weird because of the order of static initialization. Am I wrong?
Thank you guys and I hope you have enough information.
It is defined as text order - ยง17.11 in ECMA 334:
If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor.
As an aside, this gets particularly interesting if you consider partial classes, in which case : it is not defined.
If in doubt, move the initialization explicitly to a static constructor.
As for why; consider (note: these are just my own thoughts):
"definite assignment" is the thing that usually stops this being an issue, but "definite assignment" does not apply to fields
analysing the code in full detail is computationally complex (I'm thinking "halting", perhaps) - so it could only offer an incomplete veneer of safety (which is artificial and could lead to problems in any non-trivial scenario)
and due to the partial classes issue, the full order itself is not strictly defined; so it cannot handle the general case - and again, covering a specific case (single class fragment etc) is back to the "thin veneer" (where it only warns for the obvious cases, but can't help with the non-trivial ones)
Normally the compiler warns you if you are trying to use members before they are initialised.
In this case you circumvent this check as the static member doesn't use the other static member directly, instead it calls the constructor, which uses the other static member.
The compiler can't protect you from every possible dependency problem, only the simple ones. This is just one step too complex for the compiler to catch.
It would of course be possible for the compiler to catch something like this, but that would make it more complex for each additional level of dependency, and it's still not possible to catch every situation.

Controlling when the Static Constructor is called

In my custom attribute's static constructor, I search the loaded assembly for all classes decorated with my attribute and perform some action on them.
I would like the static constructor to be called as soon as possible during runtime, preferably before execution of the static void Main() entry point.
Currently it only gets called after I make some call to the attribute. I could make such a call elsewhere in my program, but ideally the attribute's functionality would be self-contained.
Looking for answers, I read this on MSDN:
The user has no control on when the static constructor is executed in the program.
But surely there is some tricky, sly, or mischievous workaround to get a static constructor to be called ASAP. Perhaps an attribute, reflection, or some other kind of magic could be used. Can it be done?
Because people would undoubtedly tell me that there is no good reason to do what I ask, I present my purpose and my code: I am trying to use attributes to declaratively configure a db4o factory. If my attribute's static constructor is called after I've already established a connection, then it has no effect and is useless. Therefore it must be called before my program gets a chance to establish such a connection.
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
sealed public class CascadeOnUpdateAttribute : Attribute
{
public bool Flag { get; private set; }
public CascadeOnUpdateAttribute() : this(true) { }
public CascadeOnUpdateAttribute(bool flag)
{
Flag = flag;
}
static CascadeOnUpdateAttribute()
{
var targets = from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
from attribute in type.GetCustomAttributes(typeof(CascadeOnUpdateAttribute), false).Cast<CascadeOnUpdateAttribute>()
select new { Type = type, Cascade = attribute.Flag };
foreach (var target in targets)
{
Db4oFactory.Configure().ObjectClass(target.Type).CascadeOnUpdate(target.Cascade);
}
}
}
Update:
I ended up using an abstract attribute with a static method. This way I can derive as many attributes as I like and they will all be applied to a specified config by calling this one method.
public abstract class Db4oAttribute : Attribute
{
public abstract void Configure(IConfiguration config, Type type);
public static void ApplyAttributes(IConfiguration config)
{
var targets = from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
from attribute in type.GetCustomAttributes(typeof(Db4oAttribute), false).Cast<Db4oAttribute>()
select new { Type = type, Attribute = attribute };
foreach (var target in targets)
{
target.Attribute.Configure(config, target.Type);
}
}
}
And the call site:
Db4oAttribute.ApplyAttributes(Db4oFactory.Configure());
_db = Db4oFactory.OpenFile("Test.db4o");
As Marc says, I would do it explicitly in Main if I were you.
You can invoke the type initializer for a type explicitly using the Type.TypeInitializer property and invoking it. However, this will cause it to run again even if it's already been run which could produce unexpected results.
I would personally move that code out of the static initializer completely. It's configuration code - why not just make it a static method which you can call explicitly? I'm not even sure I'd have it in the attribute class itself, but at least explicitly calling:
CascadeOnUpdateAttribute.ConfigureDb4oFactories();
is clearer than calling a dummy method or forcing type initialization some other way, just to get a side effect.
If you want the static constructor to get called, then add a dummy method to the type and simply call it at the start of your code (Main etc); if it is a trivial / empty method you might want to mark it for no inlining etc.
class SomeType {
static SomeType() {
Console.WriteLine("SomeType.cctor");
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Init() { }
}
static class Program {
static void Main() {
SomeType.Init();
Console.WriteLine("hi");
}
}
You can use reflection to call the static constructor, but I don't recommend it; if you use reflection you can actually call the .cctor multiple times, and that is never a good thing...
You can avoid the static dummy method by calling
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(CascadeOnUpdateAttribute).TypeHandle)
I think the use of the static constructor smells; I would consider refactoring your code to control access to the db4o factory so that you don't need to use it.

Can I change a private readonly field in C# using reflection?

I am wondering, since a lot of things can be done using reflection, can I change a private readonly field after the constructor completed its execution?
(note: just curiosity)
public class Foo
{
private readonly int bar;
public Foo(int num)
{
bar = num;
}
public int GetBar()
{
return bar;
}
}
Foo foo = new Foo(123);
Console.WriteLine(foo.GetBar()); // display 123
// reflection code here...
Console.WriteLine(foo.GetBar()); // display 456
You can:
typeof(Foo)
.GetField("bar",BindingFlags.Instance|BindingFlags.NonPublic)
.SetValue(foo,567);
The obvious thing is to try it:
using System;
using System.Reflection;
public class Test
{
private readonly string foo = "Foo";
public static void Main()
{
Test test = new Test();
FieldInfo field = typeof(Test).GetField
("foo", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(test, "Hello");
Console.WriteLine(test.foo);
}
}
This works fine. (Java has different rules, interestingly - you have to explicitly set the Field to be accessible, and it will only work for instance fields anyway.)
I agree with the other answers in that it works generally and especially with the comment by E. Lippert that this is not documented behavior and therefore not future-proof code.
However, we also noticed another issue. If you're running your code in an environment with restricted permissions you might get an exception.
We've just had a case where our code worked fine on our machines, but we received a VerificationException when the code ran in a restricted environment. The culprit was a reflection call to the setter of a readonly field. It worked when we removed the readonly restriction of that field.
You asked why you would want to break the encapsulation like that.
I use an entity helper class to hydrate entities. This uses reflection to get all the properties of a new empty entity, and matches the property/field name to the column in the resultset, and set's it using propertyinfo.setvalue().
I don't want anyone else to be able to change the value, but I don't want to take all the effort to custom code hydration methods for every entity either.
My many of my stored procs return resultsets that don't correspond directly to tables or views, so the code gen ORM's do nothing for me.
Don't do this.
I just spent a day fixing a surreal bug where objects could be not of their own declared type.
Modifying the readonly field worked once. But if you tried to modify it again, you'd get situations like this:
SoundDef mySound = Reflection_Modified_Readonly_SoundDef_Field;
if( !(mySound is SoundDef) )
Log("Welcome to impossible-land!"); //This would run
So don't do it.
This was on the Mono runtime (Unity game engine).
Another simple way to do this using unsafe (or you could pass the field to a C method via DLLImport and set it there).
using System;
namespace TestReadOnly
{
class Program
{
private readonly int i;
public Program()
{
i = 66;
}
private unsafe void ForceSet()
{
fixed (int* ptr = &i) *ptr = 123;
}
static void Main(string[] args)
{
var program = new Program();
Console.WriteLine("Contructed Value: " + program.i);
program.ForceSet();
Console.WriteLine("Forced Value: " + program.i);
}
}
}
The answer is yes, but more importantly:
Why would you want to? Intentionally breaking encapsulation seems like a horrifically bad idea to me.
Using reflection to change a readonly or constant field is like combining the Law of Unintended Consequences with Murphy's Law.
I just want to add that if you need to do this stuff for unit testing, then you can use:
A) The PrivateObject class
B) You will still need a PrivateObject instance, but you can generate "Accessor" objects with Visual Studio. How to: Regenerate Private Accessors
If you are setting private fields of an object in your code outside of unit testing, that would be an instance of "code smell" I think that perhaps the only other reason you would want to do this is if you are dealing with a third party library and you can't change the target class code. Even then, you probably want to contact the 3rd party, explain your situation and see if they won't go ahead and change their code to accomodate your need.

Categories

Resources