一,普通的一段代码

之前写了两个软件, 一个是阿里云客户端,一个是淘宝刷单软件,都用到了IOC技术。

我的做法是在引导程序中,把程序需要用到的DLL文件加载到IOC容器中,如下代码:

foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "Trade.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFile(file));
    }

然后通过IOC的方式创建实例

object obj = IoC.Get<IRetrievePwd>();
    IoC.Get<IWindowManager>().ShowDialog(obj);

这样的好处在于:

1,项目之间不用互相添加 DLL 文件的引用,做到了松耦合。

2,通过接口创建对象,实现了程序的多态性。

3,项目中基本上不会出现new关键字,避免了乱创建对象产生的性能损失。对象都给IOC容器管理了。

二,普通的代码引出的问题

在开发环境中,我的软件运行的很顺利,在测试环境里,也没有发现不能运行的情况。

当软件打包,发布到公网的时候,很多用户反应软件打不开。

幸运的是在监控日志中得到了相关错误信息:

An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more information.

这个错误说的大致意思就是,.net的安全机制阻止了加载一个dll文件。

三,解决方案:

随后,我在网络上找到了很多方法,现在汇总一下分享给大家:

方法一:

可以通过配置文件进行处理

<runtime>
    <loadFromRemoteSources enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

至关重要的就是这句:

<loadFromRemoteSources enabled="true" />

方法二:
也可以通过C#代码,进行处理

//以前
    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFile(file));
    }
    //替换为
    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFrom(file));
    }

把 Assembly.LoadFile(file)  替换为   Assembly.LoadFrom(file)

方法三:

还是通过C#代码处理,以字节的方式加载DLL

//以前
    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFile(file));
    }
    //替换为
    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        byte[] assemblyBuffer = System.IO. File.ReadAllBytes(file);
        AssemblySource.Instance.Add(Assembly.Load(assemblyBuffer));
    }

四:疑问

我的项目一直用  Assembly.LoadFile(file)  加载DLL,在本机上折腾是不会出现问题的。

一旦:

程序以DLL的方式发布到外网(比如上传到外网服务器,上传到阿里云)

然后:

Download到本地计算机运行,就会报错,具体错误信息,就是我第二大点提到的错误信息。

我也仔细对比了上传前的 DLL 与 通过上传再下载的DLL,没有任何区别。包括DLL的属性设置,读写状态等都没区别

但是异常就这样出现了,求原因,同仁们,你们遇上过这种问题吗?