禁用VS2015 C#编译器自动生成[Serializable]属性

时间:2015-12-08 11:55:56

标签: c# linq serialization visual-studio-2015

VS2015 C#编译器在LINQ查询的所有自动生成的辅助类上发出[Serializable, CompilerGenerated]属性。 Visual Studio的早期版本用于在此类上仅发出[CompilerGenerated]属性。

有没有办法在VS2015中禁用[Serializable]属性的自动生成?原因是我们的混淆器拒绝重命名标记为[Serializable]的类,尽管在我们的例子中它是100%安全的,因为我们不使用序列化。

以下是旧编译器生成的自动代码示例:

[CompilerGenerated]
private sealed class <>c
{
    public static readonly Program.<>c <>9 = new Program.<>c();
    // ... more stuff here
}

以下是VS2015发布的内容:

[Serializable, CompilerGenerated]
private sealed class <>c
{
    public static readonly Program.<>c <>9 = new Program.<>c();
    // ... more stuff here
}

我希望编译器停止生成[Serializable]属性。有可能吗?

2 个答案:

答案 0 :(得分:1)

我犹豫要发布这个...也许我错了,但我确信这可以导致正确的方向。

所以Roslyn是生成代码的编译器(这是VS2015中的默认编译器),它是开源的(参见here)。 LabdaRewriter.cs(here)包含将lambda重写为类并完成所有魔法的逻辑。在GetStaticFrame方法中有这一行:

_lazyStaticLambdaFrame = new LambdaFrame(_topLevelMethod, scopeSyntaxOpt: null, methodId: methodId, closureId: closureId);

现在LamdaFrame是表示生成的类的类(请参阅here)(在您的情况下<>c获取SerializableAttribute)。

请记住构造函数参数中的scopeSyntaxOpt: null部分!

这是构造函数:

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);
        }
        ...
}

还有一个名为IsSerializable的属性:

    // display classes for static lambdas do not have any data and can be serialized.
    internal override bool IsSerializable
    {
        get { return (object)_singletonCache != null; }
    }

正如您在构造函数中看到的那样,当singletonCache方法中创建实例时,_ GetStaticFrame基本上不会为空(我认为这是您不从外部捕获值的情况)你LINQ表达式(FIXME)),因此它返回true,我认为基于此属性生成的类得到SerializableAttribute。

所以我认为目前这是硬编码的,你不能改变它,除非你触摸Roslyn源代码并改进它....

答案 1 :(得分:0)

I ended up writing a simple dnlib-based tool that parses compiled assembly and changes the func searchBarTextDidEndEditing(searchBar: UISearchBar) { // Dismiss the keyboard searchBar.resignFirstResponder() // Force reload of table data self.loadObjects() } func searchBarSearchButtonClicked(searchBar: UISearchBar) { // Dismiss the keyboard searchBar.resignFirstResponder() // Force reload of table data self.loadObjects() } func searchBarCancelButtonClicked(searchBar: UISearchBar) { // Clear any search criteria searchBar.text = "" // Dismiss the keyboard searchBar.resignFirstResponder() // Force reload of table data self.loadObjects() } override func viewDidAppear(animated: Bool) { // Refresh the table to ensure any data changes are displayed tableView.reloadData() // Delegate the search bar to this table view class searchBar.delegate = self } property of every class with the [CompilerGenerated] attribute to false. Seems to work well enough for my needs.