How to use internal class of another Assembly [duplicate] - c#

This question already has answers here:
How can I access an internal class from an external assembly?
(6 answers)
Closed 8 years ago.
I have a third party assembly and I would like to use its Internal class in my new C# project.
Is it possible?
Any example would really be appreciated

internal: The type or member can be accessed by any code in the same
assembly, but not from another assembly.
You can not use internal classes of other assemblies, the point of using internal access modifier is to make it available just inside the assembly the class defined.
if you have access to the assembly code and you can modify it you can make second assembly as a friend of your current assembly and mark the assembly with following attribute
[assembly: InternalsVisibleTo("name of assembly here")]
if not you can always use reflection but be aware that using reflection on a 3rd party assembly is dangerous because it is subject to change by the vendor. you can also decompile the whole assembly and use part of the code you want if it is possible.
Suppose you have this dll (mytest.dll say):
using System;
namespace MyTest
{
internal class MyClass
{
internal void MyMethod()
{
Console.WriteLine("Hello from MyTest.MyClass!");
}
}
}
and you want to create an instance of MyTest.MyClass and then call MyMethod() from another program using reflection. Here's how to do it:
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();
}
}
}

If you're unable to modify and recompile the library, have a look at ImpromptuInterface.
https://www.nuget.org/packages/ImpromptuInterface/
Example:
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);
}
}
}
Internally, what ImpromptuInterface does is to create a dynamic assembly in memory and within that assembly, it creates a proxy class which implements the requested interface(s) and relays method calls and properties between the two. In the back end it still uses reflection but it is a slightly nicer encapsulation than doing it all through your own reflection.
Obviously there is an overhead involved with this but it is a viable last resort if you have no other option.
Useful features, include: the dynamic proxy class maps properties to fields, you can map interface methods to private, protected and internal methods in the original class. It doesn't work with static classes of methods, however.

You must create a friendly assembly, but you would need to recompile that third party assembly:
A friend assembly is an assembly that can access another assembly's
Friend (Visual Basic) or internal (C#) types and members. If you
identify an assembly as a friend assembly, you no longer have to mark
types and members as public in order for them to be accessed by other
assemblies.
You can use reflection though: How to access internal class using Reflection
Not recommendable anyway.

If it is an internal class, then the developer does not want you to use it. If you want to use a part of this code, just use Reflector and move it to a new class. It is not safe to use internal or private classes because the developer is not thinking of anyone other than themselves using it, and they could make changes in the future that break the functionality, they may not be thread safe, etc. So you should just respect their design.

You cannot do that. Have look here: Accessibility Levels (C# Reference)

Related

C# Public vs. Internal in different assemblies [duplicate]

This question already has answers here:
How do I use reflection to invoke a private method?
(11 answers)
Closed 1 year ago.
I am little bit confused.
I know that public is accessible from anywhere and internal classes are accessible only within the assembly.
But I found something strange in my code.
I've got three projects in one solution.
All projects shares the same namespace.
Project A (main executable)
namespace Everything
{
class Program
{
void Main()
{
Runner r = new();
}
}
}
Project B (library class)
namespace Everything
{
public class Runner
{
public Runner()
{
// Loads external assembly in runtime and creates instance
Assembly assembly = Assembly.Load("my.dll","my.pdb");
Type type = assembly.GetType("Everything.InternalClass");
Execute Instance = (Execute)Activator.CreateInstance(type);
}
}
public class Execute
{
//something to do
}
}
And finally Project C (my.dll) (another class library)
namespace Everything
{
class InternalClass : Execute
{
// This is executed in correct way - even it is in different assembly and it is set as internal (by default)
}
}
Why this is working properly? I was thinking, that I need to use public in my Project C - becuase it is in different assembly...
Accessibility modifiers affect where types and members are visible from normal C# code. Reflection allows you to bypass all that. You can also set private fields via reflection and more.
If you want a normal C# way to access internal types, you can use the InternalsVisibleTo attribute.
The GetType returns everything you search for. If you want to get the public members, use GetExportedTypes instead.
With reflection you can see and use all members.

Why can't I inherit from ScrollChangedEventArgs? [duplicate]

I'm noticing the compiler error The type '...' has no constructors defined generated when I erroneously attempt to instantiate a particlar class.
It lead me to wonder how I would go about writing my own class that would precipitate this message when someone attempted to instantiate it.
So the code below, what do I need to do to MyClass?
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
class MyClass
{
MyClass()
{
}
}
}
This error (CS0143) occurs if the class only defines an internal constructor and you try to instantiate it from another assembly.
public class MyClass
{
internal MyClass()
{
}
}
Also this error could be cause if you are compiling with Framework 4 or higher and embedding the Interop Types into your managed assembly. To get rid of this error you need to turn off (No embed) the Embedded Interop Types.
Instructions to turn off embedding:
On VS2010 Solution Explorer, right click on the Interop Reference that you are using.
Select Properties and look for Embed Interop Types
Change it from True to False
You can read about Embedded Interop Types here.
Pablo
I've managed to reproduce this by:
Creating a static class in a DLL
Using ildasm to decompile it to IL
Editing the IL to remove the "abstract" and "sealed" modifiers from the class
Rebuilding the DLL with ilasm
Compiling a program which tries to create an instance of the class
If you don't remove the abstract/sealed modifiers, the C# compiler recognizes it as a static class and gives a different error message. Of course, you could start off with a "normal" type and just remove the constructors, too.
EDIT: I actually thought I hadn't submitted this, as I saw the "internal" constructor one first. However, I'll leave it now as my version makes the C# compiler correct - there's a difference between a type having no accessible constructors and genuinely having no constructors :)
I believe you would need to make the constructor of the class internal in order to have it throw this exception. I believe you'll also need the class to exist in another assembly.
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
}
namespace DifferentNamespace
{
class MyClass
{
internal MyClass()
{
}
}
}
As has been said, you can get CS0143 by trying to instantiate a class with an internal constructor from outside its assembly.
But I believe it's a compiler bug. The error generated should be CS0122:
'member' is inaccessible due to its protection level
... which is the error you get if you try to instantiate a class with only a private constructor.
CS0143 used to happen (up to C# 3.0) if you tried to call a constructor for a built-in type like Double, but in C# 4.0 that now generates CS1729:
'type' does not contain a constructor that takes 'number' arguments.
if you pass an argument
Double d = new Double(1.25);
... or no error at all if you don't pass any arguments to the constructor.
Yet another option: the code might be right, but you might work on different projects in different instances of Visual Studio, and therefore you need to build the referenced project first.

Internal class access modifier doesnt work?

I really dont understand why, but it seems like the internal access modifier doesn't work :S
I've looked at this tutorial:
http://msdn.microsoft.com/en-us/library/7c5ka91b(v=vs.110).aspx
But for me, it compiles.
ALso, i have a bought a book Illustrated C# 2012. And the author explains the internal class etc etc... But still, it doesn't do anything.
Here is my complete code that works EVEN with internal access.
//Program.cs
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Class1 myclass = new Class1(); //works
myclass.display(); //works
myclass.display2(); //works even though its not public :S
Console.Read();
}
}
}
-
//Class1.cs
namespace ConsoleApplication1
{
internal class Class1
{
public void display()
{
Console.WriteLine("display()");
}
internal void display2()
{
Console.WriteLine("display2()");
}
}
}
I can even access the function internal void display2() :S
internal means "Acessible by anything in the same assembly".
Because your class Class1 and class Program are in the same assembly, class Program can access display2().
I think you've accidentally put them in the same assembly; if you look carefully at Microsoft's sample code you'll see it says "Assembly1.cs" and "Assembly2.cs"
If you are using Visual Studio, the easiest way to test this with a different assembly is to create a new class library project in the same solution. That will then count as a separate assembly. You'd have to add to the main project a reference to the new project (via Add Reference and then the Solution tab).
There's a Stack Overflow question about "What's an assembly?" if you need more info.
If both classes are in the same assembly then internal is working as expected.
The internal modifier is used to make sure that types and members are only available to files in the same assembly.
Ref: http://msdn.microsoft.com/en-gb/library/7c5ka91b%28v=vs.80%29.aspx
From MSDN;
Internal types or members are accessible only within files in the same
assembly
Since Program and Class1 in the same assembly, there shouldn't be a problem..
What does the internal modifier do exactly? It states that "The
intuitive meaning of internal is 'access limited to this program.'"
In other words, no external program will be able to access the
internal type.
The internal access modifier means the member can be accessed anywhere from within the same assembly.
In your case, the classes "Program" and "Class1" are within the same assembly, therefore, Program can access display2 (Which is also internal and within the same assembly).
If you don't want display2 to be accessed from the Program class, you could simply make it private and therefore it would only be accessible from Class1.

Emulating partial classes across assemblies

I'm trying to group together MANY helper classes into a common parent class for ease of use. For example, in my applications I want to do
Tools.StringTool.foo(..)
Tools.NumberTool.bar(..)
Tools.NetworkTool.something(...)
The idea here is to organize all the tools under a common Tools class so that intellisense can bring them all up when I type "Tools.".
Defining all the tools under a parent static partial class Tools works fine but not for Tools in a different assembly.
I tried to emulate static partial classes across assemblies by replacing the parent Tools class with a namespace X.Y.Tools, but for code written outside X.Y namespace, I need to fully qualify each tool before using it.
i.e. in app code
Tools.MyTool(..) // won't compile
X.Y.Tools.MyTool(...) // will compile but ugly
Any suggestions how I can solve this issue or alternative approaches for organizing the tools?
You can use extension methods in this case. All extension methods defined in classes within a namespace are made available when that namespace is imported.
This way you'd have static classes like MyUtilityNamespace.MyClassInAssembly1 and MyUtilityNamespace.MyClassInAssembly2 that all provide extension methods onto a single class instance, but this has ugliness associated with getting that class instance, like so:
// in central assembly
class Tool {
private static Tool _t = new Tool();
public static Tool T { get { return _t; } }
}
// in utility assembly 1
public static class MyExtensionClassInAssembly1 {
public static void SomeUtilityMethodX(this Tool tool, Object arg1, Object arg2) {
// do something
}
}
// in utility assembly 2
public static class MyExtensionClassInAssembly2 {
public static void SomeUtilityMethodY(this Tool tool) {
// do something
}
}
You'd use it like so:
Tool.T.SomeUtilityMethodX( Tool.T.SomeUtilityMethodY(), null );
it isn't pretty, but means you only need to import an namespace once, and the Tool.T is constant, there's no need to memorize StringTool or NetworkTool.
Another alternative is to use namespace or type aliasing, however this is laborious as you need to specify the using Tools = X.Y.Tools.MyTool; line on every source file you have.
Turns out the easiest way to do this is simply use namespaces
// in project 1
namespace Tools {
public static class NetworkTool {
}
}
// in project 2
namespace Tools {
public static class FileTool {
}
}
// in client code (references both projects)
Tools.NetworkTool.SomeMethod();
Tools.FileTool.SomeMethod()

Why would I need a using statement to Libary B extn methods, if they're used in Library A & it's Library A my client uses?

I have:
Main Program Class - uses Library A
Library A - has partial classes which mix in methods from Library B
Library B - mix in methods & interfaces
Why would I need a using statement to LibaryB just to get their extension methods working in the main class? That is given that it's Library B that defines the classes that will be extended.
EDIT - Except from code
// *** PROGRAM ***
using TopologyDAL;
using Topology; // *** THIS WAS NEEDED TO GET EXTN METHODS APPEARING ***
class Program
{
static void Main(string[] args)
{
var context = new Model1Container();
Node myNode; // ** trying to get myNode mixin methods to appear seems to need using line to point to Library B ***
}
}
// ** LIBRARY A
namespace TopologyDAL
{
public partial class Node
{
// Auto generated from EF
}
public partial class Node : INode<int> // to add extension methods from Library B
{
public int Key
}
}
// ** LIBRARY B
namespace ToplogyLibrary
{
public static class NodeExtns
{
public static void FromNodeMixin<T>(this INode<T> node) {
// XXXX
}
}
public interface INode<T>
{
// Properties
T Key { get; }
// Methods
}
}
Extension methods are only available if you import the namespace that they are defined in.
Otherwise, the compiler would need to resolve against every single extension method in every single referenced library, which would slow down the compile time.
Also, that would make it impossible to use an extension method if a different namespace contains an extension method with the same signature.
In summary, extension methods are features in their own right and require their namespace to be imported; they are not automatically imported with the namespace of the class that they extend.
This is an unfortunate discoverability issue with extension methods. In order to make them available you need to add a using statement for the namespace containing the static class that has the extensions. Check out this blog about extension methods.
Here is some background on extension methods:
So how is the compiler to know which
extension method to bind? The compiler
looks for extension methods in the
innermost namespace when the call is
made for extension methods and then in
all the namespaces imported by the
"using" clause. This process is
followed moving outward until we reach
the topmost namespace.
Since extension methods can be
imported in to the current context by
the "using" clause and bound to any
object which is assignable(see
convertibility section for details) to
the instance parameter, all sorts of
interesting possibilities open up for
extending the methods implemented by a
type. This can simply be done by
importing a library of extension
methods and using these methods as if
they were declared on a type that you
don't own. This means that
Depending on the library you import the code can be made to do different
things.
The client gets an interesting way to extend a type that he does not own.
My understanding is that using extension methods is just like using any other type, except that you can't qualify them (that is just syntactically impossible), hence the need for using statement. Since you can define multiple of them in different classes in different namespaces, the compiler needs a way to resolve ambiguity.
I envisage that in future Visual Studio will add a feature to import the right namespace when you type in the method name, in a similar way it does so for class and interface names.
Consider this scenario:
namespace FruityNamespace {
public static class FruityExtensions {
public static string ToFunString(this int value) {return value + " bananas"; }
}
}
namespace VegetablNamespace {
public static class VegetablyExtensions {
public static string ToFunString(this int value) {return value + " carrots"; }
}
}
//In some other source file
static void Main(/**/) {
int things = 3;
3.ToFunString(); //error CS1061: 'System.Int' does not contain a definition for 'ToFunString' and no extension method 'ToFunString' accepting a first argument of type 'System.Int' could be found (are you missing a using directive or an assembly reference?)
}
In order to use any of those extension methods you need to import the right namespace:
using FruityNamespace;
//OR
using VegetablyNamespace;
You might ask what happens when you import both namespaces. You get a compiler error just like this:
error CS0121: The call is ambiguous between the following methods or properties: 'VegetablNamespace.VegetablyExtensions.ToFunString(int)' and 'FruityNamespace.FruityExtensions.ToFunString(int)'

Categories

Resources