同类型为什么要强制转换(自己强转成自己)/ASP.NET Web程序重复引用(引用来自同一文件)问题(已解决)?

这篇文章由 在 星期二, 8 一月, 2019 发表。

最后的补充和结论

经过几番实验和查阅文档,得出结论:
这个重复引用/强制转换(自己强转成自己)的问题,是由于编译器对App_Code文件夹特殊处理造成的。
我的理解和解释如下(欢迎纠正):

App_Code文件夹下的文件,会在运行时进行编译,这也是为什么我们创建在App_Code文件夹下的.cs文件默认生成操作是“内容”而不是“编译”了。这个目录的作用,是存放那些需要动态修改的代码(我的理解就像asp),这个目录下的代码,是以源码形式存在于项目中,等到访问时才进行编译(这也解释了为什么我遇到的这个错误,编译可以通过,但是运行时会报错)。当访问这个目录下的类时,这个类就被第二次编译,所以会出现重复定义/类型不明确需要强制转换的问题。根据《在ASP.NET Web Application中使用App_Code文件夹引发的异常》这篇文章的解释,如果用反编译工具打开Temporary ASP.NET Files文件夹下我们项目相关的那个DLL,应该可以看到App_Code下面的类被二次编译(我没有实验,但我感觉是可能的)。

解决办法:

由于我是先解决的问题,然后再寻求的原因。所以我的解决办法是采用了caozhy同学的建议,将App_Code下所有共享的代码剪切出来创建了一个新的Library,然后在WebApplication里引用了这个Library,由于这样,App_Code下就不存在代码了,所以我的问题也相当于变相的解决了。
同样的解决办法还有,就像我刚刚那样,重新创建一个非App_Code目录,存放那些公用代码,结论也是可行的。

参考:

  • 《在ASP.NET Web Application中使用App_Code文件夹引发的异常》连接:https://www.cnblogs.com/johnnyqian/archive/2012/05/19/2509302.html
  • 《Shared Code Folders in ASP.NET Web Site Projects》连接:https://docs.microsoft.com/en-us/previous-versions/t990ks23(v=vs.140)
  • 《App_Code folder doesn’t work with Web Application Projects (WAPs)》连接:http://vishaljoshi.blogspot.com/2009/07/appcode-folder-doesnt-work-with-web.html

* 补充7:

本着好奇学习的原则,我特意创建了一个包含错误的项目,上传到了github,求老师讲解。谢谢。
https://github.com/awolfnet/test

编译时有个警告,但可以编译通过,但运行时会报错

编译警告:

CS0266  无法将类型“EEGProxy.App_Code.HTTP.METHOD [App_Web_r13cya2o, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]”隐式转换为“EEGProxy.App_Code.HTTP.METHOD [EEGProxy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]”。存在一个显式转换(是否缺少强制转换?)  EEGProxy    E:\visualstudio2015\Projects\EEGProxy\EEGProxy\App_Code\Prerouting.cs   38  

运行时错误:

编译器错误消息: CS0266: Cannot implicitly convert type 'EEGProxy.App_Code.HTTP.METHOD [E:\visualstudio2015\Projects\EEGProxy\EEGProxy\App_Code\Utils\HTTP.cs(19)]' to 'EEGProxy.App_Code.HTTP.METHOD [C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\eegproxy\728b4be6\64b07da6\assembly\dl3\5c9e5e68\1dd6f07e_a892d401\EEGProxy.dll]'. An explicit conversion exists (are you missing a cast?)

首先定义绝对没有重复,这个我是确认过了的。

查找了不少资料,大部分都说是自己引用了自己,但是我无论在项目属性里的引用页面、还是解决方案资源管理器里的“引用”树形目录里,都没有发现对项目自身的引用。

这个错误有时候会自己消失,有时候会出现,这些代码都放在APP_CODE目录下,.cs文件的生成操作已经改成了“编译”。

异常代码:

        public RoutedPackageModel RoutePackage(HTTP.METHOD method, string path, HttpRequestHeaders headers, byte[] payload)
        {
            _routedPackage.Payload = payload;
            _routedPackage.Headers = CopyHeadersFrom(headers);
            _routedPackage.Headers.Add(HttpRequestHeader.ContentType, "application/json");
            _routedPackage.Destination = GetDestinationInRouteTable(headers.Host);
            _routedPackage.Method = method; <<-此句会报错
            _routedPackage.Path = path;
            return _routedPackage;
        }

##**相关类:**

    public class RoutedPackageModel
    {
        public enum ACTION
        {
            DROP,
            REJECT,
            ACCEPT,
        }

        public HTTP.METHOD Method { set; get; }

        public string Initiator { set; get; }
        public string Source { set; get; }
        public string Original { set; get; }
        public string Destination { set; get; }
        public string Path { set; get; }
        public WebHeaderCollection Headers { set; get; }

        public byte[] Payload { set; get; }
    }

        public class HTTP
    {
        public enum METHOD
        {
            GET,
            POST,
            PUT,
            DELETE,
            HEAD,
            OPTIONS,
            TRACE,
            PATCH,
        }

        public enum SCHEMA
        {
            HTTP,
            HTTPS
        }
}

这个错误有时候会自己好-_-,有时候又会突然出现。不知道从哪里下手。

* 补充:

一开始我以为是HTTP这个类名与系统定义冲突,随即改成了MYTTP,错误依旧:

CS0266: Cannot implicitly convert type 'EEGProxy.App_Code.MYHTTP.METHOD [E:\visualstudio2015\Projects\EEGProxy\EEGProxy\App_Code\Utils\HTTP.cs(19)]' to 'EEGProxy.App_Code.MYHTTP.METHOD [C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\eegproxy\728b4be6\64b07da6\assembly\dl3\5c9e5e68\4626695d_ab92d401\EEGProxy.dll]'. An explicit conversion exists (are you missing a cast?)


* 补充2:

具体情况是这样:是我在APP_CODE\Utils下有一个HTTP.CS的类,然后同项目里其他类都在用这个HTTP.CS类里的一个枚举。

* 补充3:

在RoutePackage函数的参数定义中,HTTP.METHOD有一个绿色的浪线,会有一个警告:

class EEGProxy.App_Code.MYHTTP

"E:\visualstudio2015\Projects\EEGProxy\EEGProxy\App_Code\Utils\HTTP.CS"中的类型"MYHTTP"与"EEGProxy,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"中的导入类型"MYHTTP"冲突。请使用"E:\visualstudio2015\Projects\EEGProxy\EEGProxy\App_Code\Utils\HTTP.cs"中定义的类型。

这个警告明明提示的都是同一个文件。

* 补充4:

我什么也没改,清理几次项目,打开关闭vs,重新生成,暂时可以了,每次我都是这样解决,但是不知道根本原因在哪。
先继续干活吧,等一会数据调通了,根据那位同学的建议把那些工具类的代码新建一个项目,生成dll,然后在主项目里引用它试试。

* 补充5:

我还是不理解,在同项目中,多个类引用同一个类中的枚举类型,为什么会报这个错误?
现在具体情况是这样的,
一个HTTP类,里面有个枚举类型,叫METHOD,然后另外一个模型类,叫RoutedPackageModel,其中一个属性就是HTTP.METHOD,然后在Prerouting类中有一个方法,RoutePackage,其中一个参数就是HTTP.METHOD,然后在方法内部使用这个参数时,就会出现这个错误!

* 补充6:

我创建了一个只有3个类的项目,问题依旧,我的环境是VS2015,版本14.0.25431.01 Update3,.net framework 版本4.7.02558,
刚刚试了下用同时的vs2017,是同样的毛病。

代码现在放到了网盘https://pan.baidu.com/s/1NCneJV9NJM9DlmHLQhQCaQ
回家后我上传到github。
我就是特别好奇,是怎么回事,希望大家帮我解惑。
谢谢。

* 补充7:

本着好奇学习的原则,我特意创建了一个包含错误的项目,上传到了github,求老师讲解。谢谢。
https://github.com/awolfnet/test

* 补充8:

我又做了一个实验,过程如下:
目录结构:
App_Code\ClassInAppCode.cs
App_Code\EnumInAppCode.cs
TestCode\ClassInTestCode.cs
TestCode\EnumInTestCode.cs

一共四个文件,Enum开头的两个类文件分别定义了两个枚举类型:

EnumInAppCode.cs:
    public class EnumInAppCode
    {
        public enum EIAC
        {
            A,
            B
        }
    }

EnumInTestCode.cs:      
        public class EnumInTestCode
    {
        public enum EITC
        {
            A,
            B
        }
    }

然后两个Class是这样定义的:

ClassInAppCode.cs:
    public class ClassInAppCode
    {
        public void A(EnumInAppCode.EIAC eiac, EnumInTestCode.EITC eitc)  //这个函数的参数会报错
        {
            EnumInAppCode.EIAC _eiac; //<<-这里会报错
            EnumInTestCode.EITC _eitc;
            _eiac = eiac;//<<-这里会报错
            _eitc = eitc;
        }
    }

ClassInTestCode.cs
    public class ClassInTestCode
    {

        public void A(EnumInAppCode.EIAC eiac, EnumInTestCode.EITC eitc)
        {
            EnumInAppCode.EIAC _eiac;
            EnumInTestCode.EITC _eitc;
            _eiac = eiac;
            _eitc = eitc;
        }
    }

然后得出这样一个结果,就是当枚举类型和代码同在App_Code文件夹时,会出现这个异常。
去查了文档:https://docs.microsoft.com/en-us/previous-versions/ex526337(v=vs.140)
文档中描述说:

App_Code

Contains source code for shared classes and business objects (for example, ..cs, and .vb files) that you want to compile as part of your application. In a dynamically compiled Web site project, ASP.NET compiles the code in the App_Code folder on the initial request to your application. Items in this folder are then recompiled when any changes are detected.

Note

You can add any type of class file to the App_Code folder in order to create strongly typed objects that represent those classes. For example, if you put Web service files (.wsdl and .xsd files) in the App_Code folder, ASP.NET creates strongly typed proxies for those classes.

Code in the App_Code folder is referenced automatically in your application. The App_Code folder can contain subdirectories of files, which can include class files that in different programming languages. For more information, see Shared Code Folders in ASP.NET Web Site Projects and codeSubDirectories Element for compilation (ASP.NET Settings Schema).

重点在这句:**Code in the App_Code folder is referenced automatically in your application**
从现象来看,我怀疑是这个自动引用的问题,但我不知道如何解决。

2 Responses to “同类型为什么要强制转换(自己强转成自己)/ASP.NET Web程序重复引用(引用来自同一文件)问题(已解决)?”

  1. shaochuang

    你就跟消失了一样…寻都寻不到哈.

  2. 哎 博客越来越少了


Leave a Reply