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.
Related
This question already has answers here:
Closed 10 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Possible Duplicate:
Why does C# not provide the C++ style ‘friend’ keyword?
I'd like the private member variables of a class to be accessible to a Tester class without exposing them to other classes.
In C++ I'd just declare the Tester class as a friend, how do I do this in C#? Can someone give me an example?
There's no direct equivalent of "friend" - the closest that's available (and it isn't very close) is InternalsVisibleTo. I've only ever used this attribute for testing - where it's very handy!
Example: To be placed in AssemblyInfo.cs
[assembly: InternalsVisibleTo("OtherAssembly")]
The closest equivalent is to create a nested class which will be able to access the outer class' private members. Something like this:
class Outer
{
class Inner
{
// This class can access Outer's private members
}
}
or if you prefer to put the Inner class in another file:
Outer.cs
partial class Outer
{
}
Inner.cs
partial class Outer
{
class Inner
{
// This class can access Outer's private members
}
}
Take a very common pattern. Class Factory makes Widgets. The Factory class needs to muck about with the internals, because, it is the Factory. Both are implemented in the same file and are, by design and desire and nature, tightly coupled classes -- in fact, Widget is really just an output type from factory.
In C++, make the Factory a friend of Widget class.
In C#, what can we do? The only decent solution that has occurred to me is to invent an interface, IWidget, which only exposes the public methods, and have the Factory return IWidget interfaces.
This involves a fair amount of tedium - exposing all the naturally public properties again in the interface.
There isn't a 'friend' keyword in C# but one option for testing private methods is to use System.Reflection to get a handle to the method. This will allow you to invoke private methods.
Given a class with this definition:
public class Class1
{
private int CallMe()
{
return 1;
}
}
You can invoke it using this code:
Class1 c = new Class1();
Type class1Type = c.GetType();
MethodInfo callMeMethod = class1Type.GetMethod("CallMe", BindingFlags.Instance | BindingFlags.NonPublic);
int result = (int)callMeMethod.Invoke(c, null);
Console.WriteLine(result);
If you are using Visual Studio Team System then you can get VS to automatically generate a proxy class with private accessors in it by right clicking the method and selecting "Create Unit Tests..."
You can simulate a friend access if the class that is given the right to access is inside another package and if the methods you are exposing are marked as internal or internal protected. You have to modify the assembly you want to share and add the following settings to AssemblyInfo.cs :
// Expose the internal members to the types in the My.Tester assembly
[assembly: InternalsVisibleTo("My.Tester, PublicKey=" +
"012700000480000094000000060200000024000052534131000400000100010091ab9" +
"ba23e07d4fb7404041ec4d81193cfa9d661e0e24bd2c03182e0e7fc75b265a092a3f8" +
"52c672895e55b95611684ea090e787497b0d11b902b1eccd9bc9ea3c9a56740ecda8e" +
"961c93c3960136eefcdf106955a4eb8fff2a97f66049cd0228854b24709c0c945b499" +
"413d29a2801a39d4c4c30bab653ebc8bf604f5840c88")]
The public key is optional, depending on your needs.
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)
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.
My C# project has references to two third party DLLs. This is important because it means I don't have access to source code and can't modify or recompile these two DLLs.
Let's call them dll A and dll B. Here's what dll A looks like:
namespace ThirdParty.Foo
{
public class Bar
{
...snip...
}
public class Something
{
public Bar MyProperty { get; set; }
}
}
And here's what dll B looks like:
namespace ThirdParty.Foo
{
public class Bar
{
...snip...
}
public class SomethingElse
{
public Bar MyProperty { get; set; }
}
}
As you can see, they have the same namespace and they both define a class with the same name. My C# code needs a reference to both DLLs. I use the alias property on the reference to be able to distinguish between the two references and I also extern alias firstDll and extern alias secondDll at the top of my C# file. So far so good.
It seems obvious to me that the type of Something.MyProperty is firstDll.ThirdParty.Foo.Bar and the type of SomethingElse.MyProperty is secondDll.ThirdParty.Foo.Bar but for some reason, Visual Studio gets confused and resolves the type of both properties to the same Bar class in firstDll.
Is there a way for me to "force" VisualStudio to resolve the correct type?
EDIT:
the error I'm getting in Visual Studio is: Cannot implicitly convert type 'ThirdParty.Foo.Bar [d:\MySolution\References\Second.dll]' to 'ThirpParty.Foo.Bar [d:\MySolution\References\First.dll]'
Create a DLL that will serve as a wrapper for DLL A. Let's call the new DLL "C". Your project will then reference DLL B and C.
If the two types have the same name and namespace, then you are pretty much stuck. In C#, the name/identifier is quite important, "best fit" will only work in special situations.
However, you could write wrappers for the two different types, and make those wrappers have different names. By having two different (or even one) project just for the wrapper, you could have only one reference, thus effectively resolving the conflict "by force".
Something that works(for me it did referenced correctly) is the following,first(as you probably already did)click each dll in the references and assign an alias and place the proper extern alias.After to use the class Something and SomethingElse(and properly assign the Bar Property) create one class for each of those classes(Something and SomethingElse)and derive from them and shadow the MyProperty property:
public class TestFirst : first.ThirdParty.Foo.Something
{
//here you shadow and since you must provide the alias
//and the fully qualified name it will bet set to the
//right Bar class,same bellow in testsecond.
public first.ThirdParty.Foo.Bar MyProperty { get; set; }
}
public class TestSecond : second.ThirdParty.Foo.SomethingElse
{
public second.ThirdParty.Foo.Bar MyProperty { get; set; }
}
After its just business as usual:
TestSecond t = new TestSecond();
t.MyProperty = new second.ThirdParty.Foo.Bar();
I would load the dlls explicitly via Assembly.Load then do a createinstance on the types you need then invoke the methods via dynamic - that's because I am lazy.
The other (not lazy) way is to then use reflection to find the method and invoke it.
Since you have an extreme case here where the two assemblies not only have the same namespace, but also the same full assembly name (meaning the types have the same assembly-qualified name), you may want to consider more extreme measures to resolve it. If it's a fully managed DLL (no native code mixed in) and not strong named (or you're okay with removing the strong naming), you may be able to get away with a procedure like this:
Run ildasm and output to a .il file on disk.
Modify the .il file using a careful search and replace to change the root namespace for all types (be cautious for inner namespaces or type names that contain the same text as the root namespace.)
Run the modified file through ilasm to build a new .dll with the changes.
You can use the keyword var instead of specifying the type explicitly to avoid ambiguous references
var x = new ThirdParty.Foo.Something();
var y = new ThirdParty.Foo.SomethingElse();
var barX = x.MyProperty;
var barY = y.MyProperty;
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)'