类型“动作< T1,T2,T3>"表示为“动作".存在于2个DLL中,如何指定要使用哪个DLL或避免使用其中一个? [英] The type "Action<T1,T2,T3>" exists in 2 DLLs, how do I specify which one to use or just avoid one?

查看:63
本文介绍了类型“动作< T1,T2,T3>"表示为“动作".存在于2个DLL中,如何指定要使用哪个DLL或避免使用其中一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Unity3D制作了一个应用,并使用此socket.io插件,但是当我使用Unity 2019.1时,出现以下错误:

 /.../Unity.app/Contents/Resources/PackageManager/BuiltInPackages/com.unity.timeline/Runtime/TrackAsset.cs(17,38):错误CS0433:类型'Action< T1,T2,T3>'在'WebSocket4Net,Version = 0.14.1.0,Culture = neutral,PublicKeyToken = eb4e154b696bf72a'和'mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089'中都存在 

那是因为Action是在我使用的WebSocket4Net中定义的,即使我没有使用该特定的引用,也有在System中的定义,而我又没有使用.

Unity正在使用System.Action,而WebSocket4Net中的一个用于从Newtonsoft.Json库中生成JSON,我没有使用它,但严格将其链接到WebSocket4Net,并且不能将其删除./p>

每当Unity使用它时,我都尝试指定 System.Action ,但这不是解决方案,错误仍然存​​在.

尝试删除WebSocket4Net并删除了该错误,但是创建了一个新错误:

 'HashSet< GameObject>'不包含包含"的定义,并且没有可访问的扩展方法包含"接受类型为"HashSet< GameObject>"的第一个参数可以找到(您是否缺少using指令或程序集引用?) 

默认情况下,HashSet应具有此方法.

试图从plugins文件夹中删除所有3个DLL,以避免出现这些问题,但是那样我就没有套接字了,

有什么办法可以解决这个问题?我不想深入库中进行错误修复,但是还有其他解决方案吗?

解决方案

我假设您的意思是在相同的完整名称空间中";如果该假设不正确并且它们只是在不同的命名空间中,则:只需使用全名限定,即 global :: Foo.Bar.What 而不是>随便.为了方便起见,您也可以在每个文件的基础上添加使用别名",即

 使用Mwahaha = global :: Foo.Bar.What; 

,现在您每次在该文件中的 global :: Foo.Bar.What 中都可以使用 Mwahaha 作为别名./p>


所以;回到我的假设,您的意思是在相同的完整名称空间中":

与完整类型名称冲突是一个主要的难题,如何解决它在很大程度上取决于您的构建链.这里最简单的解决方法是鼓励库作者不要这样做,如果他们现在添加的用于兼容性的内容现在可用,则可以使用 [assembly:TypeForwardedTo(...)] 在正式"位置(即,如果库A添加了一种类型,然后在某个地方添加了正式"版本,则库A可以删除其版本,并添加 [assembly:TypeForwardedTo(typeof(TheType))] ,其中 TheType 现在来自官方"库,并且所有应该都能正常工作而不会中断调用者(如果类型)是真正兼容的;要求A的类型的调用者会自动将其重定向到正式版本 ,甚至无需重新编译.

否则...

编译器支持此功能,但可以通过外部别名"来实现.当您引用任何dll时,默认情况下它将获取 global 命名空间别名.但是,专门针对这种情况,您可以覆盖它并告诉它要针对每个dll使用哪个名称空间.因此,您可以说来自 a.dll 的所有内容都进入了 global (即默认值),但是来自 b.dll 的所有内容都进入了 blah 名称空间别名.然后,您需要使用 外部别名 在您要从 blah (即从 b.dll )访问内容的每个文件中.这很快就很烦人,但可以.简短的版本是:

 外部别名等等; 

,然后在该文件中每个位置使用 blah :: Foo.Bar.What 来引用 b.dll ;或与使用别名"结合使用:

 外部别名等等;使用Mwahaha = blah :: Foo.Bar. 

现在是 Mwahaha 指的是 b.dll 中的 Foo.Bar.every ,但仅在该文件中


上面的文章介绍了如何使用 csc 指定per-dll别名,但实际上几乎没有人直接使用 csc .

对于Visual Studio中的旧式csproj,可以在引用的属性窗口中指定别名.对于新型csproj,您必须使用丑陋的技巧:

 <目标名称="ChangeAliasesOfReferences"BeforeTargets ="FindReferenceAssembliesForReferences; ResolveReferences">< ItemGroup>< ReferencePath Condition ='%(FileName)'=='b'"><!-dll->< Aliases> blah</Aliases>< ;!-名称空间别名-></ReferencePath></ItemGroup></Target> 

关于如何使用统一构建链做到这一点:您的猜测和我的一样好.

I making an app with Unity3D and using this socket.io plugin but when I'm using Unity 2019.1 I get the following errors:

/.../Unity.app/Contents/Resources/PackageManager/BuiltInPackages/com.unity.timeline/Runtime/TrackAsset.cs(17,38): error CS0433: The type 'Action<T1, T2, T3>' exists in both 'WebSocket4Net, Version=0.14.1.0, Culture=neutral, PublicKeyToken=eb4e154b696bf72a' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'

And that is because Action is defined both in WebSocket4Net, which I use, even tho I'm not using that specific reference and in System, which again, I'm not using.

System.Action is being used by Unity, while the one in WebSocket4Net is used to make JSON from the library Newtonsoft.Json, which I'm not using but is strictly linked to the WebSocket4Net and can't be removed.

I tried specifying System.Action whenever Unity uses that, but that's no solution, the error is still there.

Tried removing WebSocket4Net and this removes that error, but create a new error:

'HashSet<GameObject>' does not contain a definition for 'Contains' and no accessible extension method 'Contains' accepting a first argument of type 'HashSet<GameObject>' could be found (are you missing a using directive or an assembly reference?)

when HashSet should have this method by default.

Tried removing all 3 DLLs from the plugins folder in order to avoid having these issues, but then I won't have sockets,

Is there any way to fix this? I don't want to dive into the libraries to bugfix that, but is there any other solution?

解决方案

I'm assuming that you mean "in the same full namespace"; if that assumption is incorrect and they're simply in different namespaces, then: just use full name qualification, i.e. global::Foo.Bar.Whatever instead of just Whatever. You can also add a "using alias" on a per-file basis for convenience, i.e.

using Mwahaha = global::Foo.Bar.Whatever;

and now you can use Mwahaha as an alias every time you mean global::Foo.Bar.Whatever in that file.


So; going back to my assumption that you mean "in the same full namespace":

Conflicting full type names is a major pain, and how to fix it depends a lot on your build chain. The simplest fix here is to encourage library authors not to do this, perhaps using [assembly:TypeForwardedTo(...)] if the thing they added for compatibility is now available in an "official" location (i.e. if library A adds a type, then later the "official" version is added somewhere, library A can delete their version of it, and add [assembly:TypeForwardedTo(typeof(TheType))] where TheType is now from the "official" library, and everything should work correctly without even breaking callers, if the types are truly compatible; callers expecting the type in A will be redirected to the official version automatically without even needing to be recompiled).

Otherwise...

The compiler supports this, but via something called "extern aliases". When you reference any dll, by default it gets the global namespace alias. However, specifically for this scenario, you can override that and tell it which namespace to use on a per-dll basis. So you could say that everything from a.dll goes into global (i.e. the default), but everything from b.dll goes into the blah namespace alias. You then need to use extern alias in every single file where you want to access things from blah (i.e. from b.dll). This gets annoying very quickly, but works. The short version would be:

extern alias blah;

and then use blah::Foo.Bar.Whatever in every location in that file to refer to Foo.Bar.Whatever from b.dll; or combined with "using alias":

extern alias blah;
using Mwahaha = blah::Foo.Bar.Whatever;

and now Mwahaha refers to Foo.Bar.Whatever from b.dll but only in that file.


The article above covers how to specify the per-dll aliases with csc, but in reality almost nobody uses csc directly.

For old-style csproj in Visual Studio, the alias can be specified in the properties window of the reference. For new-style csproj, you have to use an ugly hack:

  <Target Name="ChangeAliasesOfReferences"
    BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
    <ItemGroup>
      <ReferencePath Condition="'%(FileName)' == 'b'"><!-- the dll -->
        <Aliases>blah</Aliases><!-- the namespace aliases -->
      </ReferencePath>
    </ItemGroup>
  </Target>

As for how to do this with the unity build chain: your guess is as good as mine.

这篇关于类型“动作&lt; T1,T2,T3&gt;"表示为“动作".存在于2个DLL中,如何指定要使用哪个DLL或避免使用其中一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆