简体   繁体   中英

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. The resolution of the call to TestAsmdef.DoTest(); is baked in at compile time so no calls to Assembly.Load will help you. 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 :

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. To use these aliases from within a program, reference them by using the extern keyword. 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. 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').

Note that you can (if you're using Visual Studio) ignore that bit about using the command-prompt. 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:

在此处输入图片说明

Set the alias for the 'guts' assembly to, say, "Guts" then use

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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