如何使用另一个Assembly的内部类

use*_*422 6 .net c# oop .net-assembly

我有一个第三方程序集,我想Internal在我的新C#项目中使用它的类.可能吗?

真的很感激任何一个例子

Ham*_*jam 11

internal:类型或成员可以由同一程序集中的任何代码访问,但不能从另一个程序集访问.

您不能使用其他程序集的内部类,使用internal 访问修饰符的目的是使其在类定义的程序集内可用.

如果您可以访问汇编代码并且可以修改它,则可以将第二个汇编作为当前汇编的朋友,并使用以下属性标记汇编

[assembly: InternalsVisibleTo("name of assembly here")]
Run Code Online (Sandbox Code Playgroud)

如果不是,你总是可以使用反射,但要注意在第三方组件上使用反射是危险的,因为它可能会被供应商更改.你也可以反编译整个程序集并使用你想要的部分代码(如果可能的话).

假设你有这个dll(mytest.dll说):

using System; 

namespace MyTest 
{ 
      internal class MyClass 
      {  
          internal void MyMethod() 
          {  
               Console.WriteLine("Hello from MyTest.MyClass!"); 
          } 
      } 
} 
Run Code Online (Sandbox Code Playgroud)

并且您想要创建一个实例,MyTest.MyClass然后MyMethod()使用反射从另一个程序调用.这是怎么做的:

using System; 
using System.Reflection;

namespace MyProgram 
{ 
    class MyProgram 
    { 
          static void Main() 
          { 
              Assembly assembly = Assembly.LoadFrom("mytest.dll");
              object mc = assembly.CreateInstance("MyTest.MyClass");
              Type t = mc.GetType(); 
              BindingFlags bf = BindingFlags.Instance |  BindingFlags.NonPublic;
              MethodInfo mi = t.GetMethod("MyMethod", bf); 
              mi.Invoke(mc, null); 
              Console.ReadKey(); 
         } 
    } 
}  
Run Code Online (Sandbox Code Playgroud)


Joh*_*ica 7

如果您无法修改和重新编译库,请查看ImpromptuInterface.

https://www.nuget.org/packages/ImpromptuInterface/

例:

namespace ImpromptuExample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Get the desired type
            Type typeObject = typeof(SampleLibrary.PublicClass).Assembly.GetType("SampleLibrary.SamplePrivateClass");
            // todo:  add error handling if typeObject is null

            // Create an instance
            object instance = Activator.CreateInstance(typeObject);
            ITest wrappedInstance = ImpromptuInterface.Impromptu.ActLike<ITest>(instance);
            MessageBox.Show(wrappedInstance.TestMethod(textBox1.Text));
        }

        public interface ITest
        {
            string TestMethod(string name);
        }
    }
}

namespace SampleLibrary
{
    public class PublicClass
    {
    }

    class SamplePrivateClass
    {
        public string TestMethod(string name)
        {
            return string.Concat("Hello ", name);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ImpromptuInterface在内部做的是在内存中和该程序集中创建动态程序集,它创建一个代理类,它实现所请求的接口,并在两者之间中继方法调用和属性.在后端它仍然使用反射,但它比通过自己的反射完成所有的封装更好.

显然这涉及到一个开销,但如果你没有其他选择,它是一个可行的最后手段.

有用的功能包括:动态代理类将属性映射到字段,您可以将接口方法映射到原始类中的private,protected和internal方法.但是,它不适用于静态类方法.