C# internal Access Specifiers, - c#

I have Created one ConsoleApplication to understand Access Specifiers.
Below is my code for internal, I can access this class from outside the Assembly.
namespace Assembly_1 //This is first assembly.
{
public class Base
{
//internal class
internal class B
{
public static void fnB()
{
Console.WriteLine("fnB");
}
}
}
}
namespace Assembly_2 //This is second assembly.
{
public class Derived : Assembly_1.Base
{
public class D
{
public void fnD()
{
B.fnB();//how can I access this class?
}
}
}
}
And this is where I am Accessing it.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Assembly_2.Derived.D d = new Assembly_2.Derived.D();
d.fnD();
}
}
}
My Question
Right now I can Access Class B and it's methods like fnB() in Derived.
Everything works fine. but How?
How can I access the B Class outside Assembly_1?

As I worte in the comments:
You are confusing the namespace and assembly terms.
You can read about it here:(Assemblies and Namespace)
Many namespaces can be defined in a single assembly.
If you would like to check and understand the internal modifier,
then you would have to create a new class library project (that will compile into a different assembly), define the Base class there
and add a reference to it in your main console application.
Then you will see that you don't have access to it anymore and the code will not compile.

How can I access the B Class outside Assembly_1?
Because you're confusing namespaces and assemblies. An assembly is a collection of one or more namespaces, contained within a .dll or .exe file.
See also: MSDN: Assemblies in the Common Language Runtime and Understanding and Using Assemblies and Namespaces in .NET.
What you call Assembly_1 and Assembly_2 are namespaces within the same assembly.
Because internal members are visible within the same assembly, you can use Assembly_1.B from Assembly_2.D, because both namespaces reside in the same assembly.

Related

c# - My .dll File isn't showing Up

I have created a .cs files that contain the following:
namespace SetUp
{
class Config
{
public static object SetConfig(int code, bool print)
{
//My Code
}
}
}
Compiled it and added the reference to my main project called 'CSharp Side', for example. Added it to my project and everything is great. But my question is how do I access 'SetConfig()'? Because it doesn't recognize 'SetUp' or 'Config' in my code.
Simply make your class as public.
namespace SetUp
{
public class Config
{
public static object SetConfig(int code, bool print)
{
//My Code
}
}
}
You can reference code in a different assembly by fully qualifying:
SetUp.Config.SetConfig(1, true);
or include the namespace with a using directive:
using SetUp;
class SomeClass
{
void SomeMethod()
{
Config.SetConfig(1, true);
}
}
Also, both the class and the method in the referenced assembly need the public modifier. Otherwise they won't be visible outside the assembly where they are defined.

Modifying / Adding to C# Partial Classes

I have got a partial class in my C# project i.e. auto-generated code from Entity Framework. Now I want to modify or add some more functionalities, properties or methods to that class. I have the auto-generated class code under EntityFrameworkModel.tt\Author.cs tab in the project while the other related classes are in another folder i.e. GraphData in the same project.
I also know that the name of partial classes should be same while file name may be different or same as well. I did same but when I defined the object for Author.cs as:
protected override EvoObject ConvertCPV(Author _author)
{
if (_author.???)
{
//...
}
}
I can't access the methods defined in GraphData\Author.cs (The question marks in example code) whereas the properties defined in EntityFrameworkModel.tt\Author.cs are only accessible.
Here I attached the Solution Explorer image as:
How can I access the properties and methods from both classes?
I have a similar set up in a project also.
To keep things tidy I also have folders where I place certain partial classes, you just need to ensure the namespace is the same as the auto generated class.
When you add a new class to a folder the namespace will automatically contain the name of the folder - you can just remove the folder name from the namespace - you should just have the Project name in this scenario.
If the namespaces are different then the partial classes are not part of the same class. This is why you can't access the new functions/Properties.
Also, even though your file name and class names can be different, it is better to keep them the same - it will be easier to find a class if the file has the same name.
Check out https://msdn.microsoft.com/en-us/library/wa80x488.aspx
It says "The partial keyword indicates that other parts of the class, struct, or interface can be defined in the namespace." It does not explicitly state this, but that implies that the partial definitions of the class must be declared in the same namespace. It doesn't matter which files in the project contain the classes, or what folders they are in.
using System;
namespace DemoConsoleApp
{
class Program
{
static void Main(string[] args)
{
SameNamespace.PartialClass.MethodOne();
SameNamespace.PartialClass.MethodTwo();
DifferentNamespace.PartialClass.MethodThree();
}
}
}
namespace SameNamespace
{
public partial class PartialClass
{
public static void MethodOne()
{
Console.WriteLine("Method One.");
}
}
public partial class PartialClass
{
public static void MethodTwo()
{
Console.WriteLine("Method Two.");
}
}
}
namespace DifferentNamespace
{
public partial class PartialClass
{
public static void MethodThree()
{
Console.WriteLine("Method Three.");
}
}
}
Make your own class outside of EntityFrameworkModel.tt - name it Author.cs, make the class partial.
The whole idea of partial is to allow code generators not to care about your code. Of you modify a generated class, the next regeneration kills the changes.
I did same but when I defined the object for Author.cs as:
Ah, no, you did not because then you claim your definition is:
protected override EvoObject ConvertCPV(Author _author)
Which is NOT defining the object.
I can't access the methods defined in GraphData\Author.cs
Because namespace? Check the namespaces - bad to have them in a subfolder when they belong in a the same namespace as EntityFrameworkModel.tt
whereas the properties defined in EntityFrameworkModel.tt\Author.cs are only
accessible.
Partial classes do not allow changes in another partial - not for the moment, a substition syntax is considered.

How does CLR differentiate classes with the same name but without namespace in different assemblies at runtime?

How does CLR differentiate classes with the same name but without namespace in different assemblies at runtime?
Example :
Assembly : Assembly1
public class Foo
{
public void Test()
{
Console.WriteLine("Assembly 1 class Foo");
}
}
Please note class Foo is not having any namespace.
Assembly : Assembly2
public class Foo
{
public void Test()
{
Console.WriteLine("Assembly 2 class Foo");
}
}
Please note class Foo is not having any namespace here too.
So Assembly1 and Assembly2 are having classes with the same name but without namespace.
Assembly : TestAssembly1 ---->Refers : Assembly1
namespace TestAssembly1
{
public class TestAssembly1Class
{
public void CallFooMethod()
{
new Foo().Test(); //How CLR would know this Foo is from Assembly 1 at runtime?
}
}
}
Assembly : TestAssembly2---------->Refers : Assembly2
namespace TestAssembly2
{
public class TestAssembly2Class
{
public void CallFooMethod()
{
new Foo().Test(); //How CLR would know this Foo is from Assembly 2 at runtime?
}
}
}
Now suppose There is one Executable say MyShell.exe which has Main method. which looks like following.
class Program
{
static void Main(string[] args)
{
new TestAssembly1Class().CallFooMethod();
new TestAssembly2Class().CallFooMethod();
}
}
So here question is that, both Foo classes are not having any namespace then, when MyShell.exe is executed how CLR will differentiate these conflicting Foo classes?
How does CLR differentiate classes with the same name but without
namespace in different assemblies at runtime?
Both types would have a different AssemblyQualifiedName
Because when the two assemblies are compiled independently prior to inclusion and the two types are each assigned a fully qualified name which includes the assembly name.
When the third assembly, which references the two previous assemblies, is compiled and names are bound the conflict is resolved via the fully qualified name.

How to get an object from a loaded dll

I see this question a fair amount on SO, and I've followed that advice, but I appear to be doing something wrong. The dll seems to load in fine but the object CreateInstance is returning is null.
I have this dll:
namespace Backfill
{
public class Module : Kernel.Module
{
public override void ModuleStart()
{
//Stuff
}
}
}
In another DLL with a DIFFERENT namespace
namespace Kernel
{
public abstract class Module
{
public abstract void ModuleStart();
}
public static void KernelStart()
{
string load_dll = #"Path to DLL";
Assembly test_dll = Assembly.LoadFile(load_dll + ".dll");
Module test_mod = (Module)test_dll.CreateInstance("Kernel.Module");
test_mod.ModuleStart();
}
}
(Module)test_dll.CreateInstance("Kernel.Module"); is returning null, though. Any idea why?
(Module)test_dll.CreateInstance("Kernel.Module")
This won't work. As you specified, the Module class which you're trying to instantiate (which, I assume, is the one from the first DLL), is not in the Kernel namespace, but in the Backfill namespace. You should therefore have something along these lines:
(Module)test_dll.CreateInstance("Backfill.Module")
Kernel.Module is an abstract class. You cannot create an instance of it directly. You need to create an instance of the derived class.
Edit: Since supplying more info:
#Antonijn has the same answer. You need to specify the type that you want directly. BackFill.Module seems like the correct one.
Before Edit:
If you have the same names in multiple assemblies then yo need to use a fully qualified (including assembly name) for the type you want. For exmaple: https://stackoverflow.com/a/2300428/30225 as an possible answer.

Namespace-only class visibility in C#/.NET?

In C#, can you make a class visible only within its own namespace without living in a different assembly? This seems useful for typical helper classes that shouldn't be used elsewhere.
(i.e. what Java calls package-private classes)
You can make the classes internal but this only prevents anyone outside of the assembly from using the class. But you still have to make a separate assembly for each namespace that you want to do this with. I'm assuming that is why you wouldn't want to do it.
Getting the C# Compiler to Enforce Namespace Visibility
There is an article here (Namespace visibility in C#) that shows a method of using partial classes as a form of "fake namespace" that you might find helpful.
The author points out that this doesn't work perfectly and he discusses the shortcomings. The main problem is that C# designers designed C# not to work this way. This deviates heavily from expected coding practices in C#/.NET, which is one of the .NET Frameworks greatest advantages.
It's a neat trickā€¦ now don't do it.
I don't think that what you want is possible.
internal is assembly (strictly speaking module) privacy. It has no effect on namespace visibility.
The only way to achieve privacy of a class from other classes within the same assembly is for a class to be an inner class.
At this point if the class is private it is invisible to anything not in that class or the outer class itself.
If protected it is visible to everyone that could see it when private but is also visible to sub classes of the outer class.
public class Outer
{
private class Hidden { public Hidden() {} }
protected class Shady { public Shady() {} }
public class Promiscuous { public Promiscuous() {} }
}
public class Sub : Outer
{
public Sub():base()
{
var h = new Hidden(); // illegal, will not compile
var s = new Shady(); // legal
var p = new Promiscuous(); // legal
}
}
public class Outsider
{
public Outsider()
{
var h = new Outer.Hidden(); // illegal, will not compile
var s = new Outer.Shady() // illegal, will not compile
var p = new Outer.Promiscuous(); // legal
}
}
In essence the only way to achieve what you desire is to use the outer class as a form of namespace and restrict within that class.
No, it is possible. You can use internal class in another assembly.
For example I have a internal string extension class that located in SharMillSoft.Core assembly, if I want use it in another assembly that name is SharpMilSoft.Extension, I must use assembly attribute like as below:
using System;
using System.Linq;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("SharpMilSoft.Extensions")]
namespace SharpMilSoft.Core.Extensions.Strings.Public
{
internal static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return string.IsNullOrEmpty(data);
}
}
}
And I use this class in SharpMilSoft.Extension assembly like as below:
namespace SharpMilSoft.Extensions.Strings
{
public static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return Core.Extensions.Strings.Public.SharpStringExtensions.IsNullOrEmpty(data);
}
}
}
Note: Then SharpMilSoft.Extensions assembly will be friend assembly for SharpMilSoft.Core assembly
For more details about friend assembly, you can visit this link : Friend assemblies
If you have a single assembly you can define as many namespaces in that assembly as you want but no matter what modifier you apply in the IDE you will always be able to see the classes in other namespaces.
Not sure if it is directly possible, but a few good ways to fake it would be:
1) Have the classes that need this sort of stuff inherit from a single class which has the helper class as an internal class.
2) Use extension methods and then only reference the extension methods within the namespace.

Categories

Resources