简体   繁体   English

C# 程序集在运行时“重载”(Unity3D)

[英]C# Assembly "Overloading" at runtime (Unity3D)

This is possibly a duplicate of other questions regarding Reflection and Overloading, etc, but I think I'm struggling because I don't know what to actually call this problem so I'm not Googling it properly.这可能是关于反射和重载等的其他问题的重复,但我认为我很挣扎,因为我不知道实际上如何称呼这个问题,所以我没有正确使用谷歌搜索。

Anyway, I've got two programs.无论如何,我有两个程序。 One is a ' launcher ' and another is the ' guts '.一个是“发射器”,另一个是“胆量”。

The launcher has a class defined:启动器定义了一个类:

public static class TestAsmdef {
  public static void DoTest() {
    Debug.Log("Version 0");
  }
}

The guts then have the exact same class defined but with different debug message:胆量然后定义了完全相同的类,但具有不同的调试消息:

public static class TestAsmdef {
  public static void DoTest() {
    Debug.Log("Version 1");
  }
}

Within the launcher , I'm loading the guts assembly via:启动器中,我正在通过以下方式加载胆量程序集:

  TestAsmdef.DoTest();
  Assembly.Load(unityAssetBundle.LoadAsset<TextAsset>("guts").bytes);
  TestAsmdef.DoTest();

I'd hope to see debug output:我希望看到调试输出:

0
1

But as you probably guess, I'm seeing:但正如你可能猜到的,我看到:

0
0

I know the assembly load is definitely working as classes that do not exist at all in the launcher are available from guts after the load, but I'm not properly overloading existing classes.我知道程序集加载肯定可以正常工作,因为加载后可以从胆量中获得启动器中根本不存在的类,但是我没有正确重载现有类。 Any idea on what I'm doing wrong or what this concept is called so I can better search for a solution?关于我做错了什么或这个概念被称为什么的任何想法,以便我可以更好地寻找解决方案?

EDIT编辑

I continued poking at this trying to make sense of this Reflection black magic...我继续戳这个试图理解这个反射黑魔法......

  TestAsmdef.DoTest();
  Assembly asm = Assembly.Load(unityAssetBundle.LoadAsset<TextAsset>("guts").bytes);
  TestAsmdef.DoTest();

  Type type = asm.GetType("TestAsmdef");
  MethodInfo mi = type.GetMethod("DoTest");
  mi.Invoke(null, null);

ALSO... yields:还...产生:

0
0
0

What in the world...世界上有什么...

Yeah - Assembly.Load will load an assembly, but (as you now know) won't change what your code is doing.是的 - Assembly.Load将加载一个程序集,但(正如您现在所知)不会改变您的代码正在做什么。 The resolution of the call to TestAsmdef.DoTest();调用TestAsmdef.DoTest();的分辨率TestAsmdef.DoTest(); is baked in at compile time so no calls to Assembly.Load will help you.是在编译时完成的,因此对 Assembly.Load 的调用不会对您有所帮助。 You can trivially confirm this by going to the definition of the two calls - both will point to the same method.您可以通过转到两个调用的定义来轻松确认这一点 - 两者都将指向相同的方法。


If you need to call two methods in two types with the same namespace and names, you'll need to define an extern alias :如果您需要调用具有相同命名空间和名称的两种类型的两个方法,则需要定义一个extern 别名

To reference two assemblies with the same fully-qualified type names, an alias must be specified at a command prompt, as follows:要引用具有相同完全限定类型名称的两个程序集,必须在命令提示符下指定别名,如下所示:

 /r:GridV1=grid.dll /r:GridV2=grid20.dll

This creates the external aliases GridV1 and GridV2.这将创建外部别名 GridV1 和 GridV2。 To use these aliases from within a program, reference them by using the extern keyword.要在程序中使用这些别名,请使用 extern 关键字引用它们。 For example:例如:

 extern alias GridV1; extern alias GridV2;

Each extern alias declaration introduces an additional root-level namespace that parallels (but does not lie within) the global namespace.每个 extern 别名声明都引入了一个额外的根级命名空间,该命名空间与全局命名空间平行(但不位于其中)。 Thus types from each assembly can be referred to without ambiguity by using their fully qualified name, rooted in the appropriate namespace-alias.因此,可以通过使用它们的完全限定名称(以适当的命名空间别名为根)来毫无歧义地引用来自每个程序集的类型。

Here you only need to specify one alias (for the 'guts') because the conflicting namespace-qualified type is specified in the same place you're using it (the 'launcher').在这里,您只需要指定一个别名(对于“guts”),因为冲突的命名空间限定类型是在您使用它的同一位置(“启动器”)中指定的。

Note that you can (if you're using Visual Studio) ignore that bit about using the command-prompt.请注意,您可以(如果您使用的是 Visual Studio)忽略有关使用命令提示符的那一点。 If you add a reference to the 'guts' assembly to the 'launcher' assembly then you can specify an alias in the properties for the reference, eg:如果您将对“guts”程序集的引用添加到“启动器”程序集,则可以在引用的属性中指定别名,例如:

在此处输入图片说明

Set the alias for the 'guts' assembly to, say, "Guts" then use将“guts”程序集的别名设置为“Guts”,然后使用

extern alias Guts

and you should be able to call你应该可以打电话

// Launcher method:
TestAsmdef.DoTest();

// Guts method:
Guts:TestAsmdef.DoTest();

to call the two DoTest() methods.调用两个DoTest()方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM