【问题标题】:How to use internal class of another Assembly [duplicate]如何使用另一个程序集的内部类[重复]
【发布时间】:2015-02-04 16:37:54
【问题描述】:

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

任何例子都将不胜感激

【问题讨论】:

  • 没有反编译和重新编译就不行了...这就是internal的重点...
  • 非常感谢詹姆斯的回复。但我看到有些人建议我们可以使用 InternalsVisibleTo 或 Reflection 来做到这一点。但我无法控制在我的第三方大会中执行此操作。请指教
  • 看看 ImpromptuInterface
  • @user1878422 如果您能够更改程序集上的InternalsVisibleTo 属性,则无论如何都可以将类公开
  • @user1878422 我添加了一个在这种情况下可能对您有用的示例。

标签: c# .net oop .net-assembly


【解决方案1】:

internal:该类型或成员可以被同一个中的任何代码访问 程序集,但不是来自另一个程序集。

您不能使用其他程序集的内部类,使用internal access modifier 的目的是使其仅在定义的类的程序集中可用。

如果您可以访问程序集代码并且可以对其进行修改,则可以将第二个程序集作为当前程序集的friend 并使用以下属性标记该程序集

[assembly: InternalsVisibleTo("name of assembly here")]

如果不是,您始终可以使用反射,但请注意,在第 3 方程序集上使用反射是危险的,因为供应商可能会对其进行更改。如果可能的话,你也可以decompile整个程序集并使用你想要的部分代码。

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

using System; 

namespace MyTest 
{ 
      internal class MyClass 
      {  
          internal void MyMethod() 
          {  
               Console.WriteLine("Hello from MyTest.MyClass!"); 
          } 
      } 
} 

你想创建一个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(); 
         } 
    } 
}  

【讨论】:

  • HamidP:感谢您提供的选项,我无法使用 InternalsVisibleTo 属性。你能给我提供反射方法的例子吗?
  • @user1878422:您可以做某事的事实并不意味着您应该这样做。我强烈建议不要在您自己开发的程序集中使用反射来使用第三方内部类。你最好重新实现功能或使用其他模式,如组合或装饰器。
【解决方案2】:

如果您无法修改和重新编译库,请查看 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);
        }
    }
}

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

显然,这涉及到开销,但如果您别无选择,这是一个可行的最后手段。

有用的功能,包括:动态代理类将属性映射到字段,您可以将接口方法映射到原始类中的私有、保护和内部方法。但是,它不适用于静态方法类。

【讨论】:

  • 谢谢。我会试一试:)
【解决方案3】:

你不能那样做。看这里:Accessibility Levels (C# Reference)

【讨论】:

  • 考虑使用英语作为国际语言
  • 对不起。我在 EN 中有它作为自动翻译的原件。
【解决方案4】:

如果它是一个内部类,那么开发者不希望你使用它。如果您想使用此代码的一部分,只需使用Reflector 并将其移至新类即可。使用内部类或私有类是不安全的,因为开发人员不会考虑除了他们自己以外的任何人使用它,并且他们将来可能会做出破坏功能的更改,它们可能不是线程安全的,等等。所以你应该只是尊重他们的设计。

【讨论】:

    【解决方案5】:

    您必须创建一个friendly assembly,但您需要重新编译该第三方程序集:

    朋友程序集是可以访问另一个程序集的程序集的程序集 Friend (Visual Basic) 或 internal (C#) 类型和成员。如果你 将程序集识别为朋友程序集,您不再需要标记 类型和成员为公共的,以便其他人可以访问它们 程序集。

    您可以使用反射:How to access internal class using Reflection

    无论如何都不推荐。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-24
      • 1970-01-01
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 2017-06-04
      • 1970-01-01
      相关资源
      最近更新 更多