I'm a C# newbie, so please bear with me.
OK, so I have two classes in different assemblies that need to reference each other:
namespace AssemblyA
{
class A
{
private B MyB { get; set; }
}
}
namespace AssemblyB
{
class B
{
private A MyA { get; set; }
}
}
I understand that circular references aren't allowed, so I'm using an interface:
namespace AssemblyA
{
public interface IB
{
// whatever 'A' needs of 'B'
}
class A
{
private IB MyB { get; set; }
}
}
namespace AssemblyB
{
class B : AssemblyA.IB
{
private A MyA { get; set; }
}
}
This works, but it has the disadvantage that it exposes IB to the rest of the world. What I would like to do instead is to make IB internal. But then B cannot derive from it.
In C++, I'd make B a friend and be done. I understand that C# doesn't have friends (pun not intended, but noted), so I have to make do without. I've read that there is an attribute for that, but this will make the whole of assembly A accessible to the whole of assembly B, which I don't like. Is there a way to avoid that?
You've in fact been misinformed - C#/.NET does indeed have support for friend assemblies. You want to mark your two assemblies as Friend Assemblies, which MSDN defines as the following:
An internal type or internal member in an assembly can be accessed from another assembly.
So, simply place the following attribute anywhere in one of your code files in your project (I would choose AssemblyInfo.cs).
[assembly:InternalsVisibleTo("name_of_friend_assembly")]
It seems that the big issue here is letting assembly B see one specific member of assembly A.
This negates, according to the comments reiterating part of the original question, the feasibility of using the well-documented InternalsVisibleTo attribute.
Or does it?
Have you considered making a new assembly, C, with the IB interface marked internal and its own InternalsVisibleTo attributes out to A and B?
This at least exposes IB in a controlled fashion, without exposing all of A to B. I'm not a huge fan of the solution (I would personally just go ahead and use InternalsVisibleTo on A as has been suggested, then document the rest of my internals to keep others in line), but I understand where you're coming from -- and this at least solves the problem.
You could use InternalsVisibleToAttribute
http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx
Related
I just know I'm being an idiot, so somebody please tell me how.
Setup is simple:
Create a solution with three projects (.Net framework, class libraries) named InherTest, InherTest.Base, and InherTest.Base.Inherited
In InherTest.Base, add the following class:
namespace InherTest.Base
{
public abstract class BaseClass
{
internal abstract string MEMBER_1 { get; }
}
}
Copy the exact same code into InherTest, including the namespace.
In InherTest.Base.Inherited, add the following class:
namespace InherTest.Base.Inherited
{
public class Inherited : BaseClass
{
internal override string MEMBER_1 { get; }
}
}
Add a project reference in InherTest.Base.Inherited to InherTest.Base. Note the errors ("abstract member not implemented" and "no suitable member found to override").
Remove that reference and replace it with one to InherTest. Observe that the inheritance also fails.
Why don't they both work?
Edit: Originally I stated that one test would fail and the other would succeed; however, both inheritance attempts fail in the above scenario.
This is because the string is internal so limited to it's own project
Why don't they both work?
They should both fail if they contain the same code as you claim. If that is not the case then the code is different between the 2 projects, specifically the MEMBER_1 is probably declared as public in InherTest project.
The only way that a reference to InherTest would work with the same code you posted is if you have this assembly level attribute InternalsVisibleToAttribute in the project InherTest
[assembly:InternalsVisibleTo("InherTest.Base.Inherited")]
Inherited Namespaces are in different project. (Name spaces seems like together but they are not in a same assembly). You can read that article.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/internal
I created a assembly having a child class that derives from a parent defined in another assembly.
When I add reference to the child, Visula studio also requires reference to be added to the parent.
Why is it so and how can I prevent it without losing any functionality?
What you describe is partially possible. You can eliminate the need for them to explicitly reference the hidden assembly, but that assembly will still get pulled in at compiled time, and required at runtime.
Let's say you have these classes defined:
// in assembly 1:
public class A
{
public virtual void Foo() { }
}
// and in assembly 2:
// requires explicit reference to assembly 1 to use
public class B : A
{
public override void Foo() { }
public A Value { get; set; }
public void Foo(A value) { }
}
// has implicit reference to assembly 1, but end user can ignore
public class C
{
private A Value { get; set; }
internal void Foo(A value) { }
protected internal A Bar() { return new A(); }
}
// usable at runtime even if assembly 1 is missing, as long as you don't call Foo()
public class D
{
public void Foo() { A blah = new A(); }
public void Bar() { }
}
If the end user uses class B, they will require an explicit reference to assembly 1. Since A is part of B's public interface, in order to use B, you have to know about A. There are 3 different public references to A, and any of them will require knowing about A to use B.
However, class C makes references to A, but all references are private/internal/local. Since every reference to A is hidden from the outside, the end user doesn't have to explicitly know about assembly 1. It will still be required at runtime, but you don't have to add it as a reference, it's an indirect reference.
And if the end user uses class D, without ever using B or C, assembly 1 will only get loaded if you call D.Foo(), which has a local variable of type A. You can actually use D.Bar() freely even if assembly 1 is completely missing at runtime. Although if you call D.Foo() and assembly 1 is missing, you'll get an exception.
In C/C++, class definition is present in a .h header file. That gives you ability to reference information about a class (as needed e.g. when you want to inherit from that class) without the need to source file with implementation information. The downside is code duplication (implementation in .cpp file needs to repeat most of the information in .h file).
In .NET world the design is different: an assembly contains both the code for the class (CLR bytecode) as well as all the metadata (class name, information about its members etc.) needed to e.g. inherit from that class.
A consequence of that design is that in order to use a class defined in assembly A that inherits from a class in assembly B, .NET needs both A and B assemblies. Or more generically: if you use anything from a given assembly (a class, an enum, a struct), either directly or indirectly, you need to reference that assembly.
I'm not sure what you want to prevent. If you decide to split your code in two assemblies like you described, there's no way around the need to reference both of them.
There are, of course, different ways of structuring your code but not knowing what goal you're trying to achieve by splitting the code into 2 assemblies in the first place, it's impossible to make a useful suggestion.
I got for example two classes cross referencing each other. I want to compile these files to separate dll files.
File 1:
public class A
{
public B bObj;
public A ()
{
bObj = new B (this);
}
public void TestMethod()
{
}
}
File 2:
public class B
{
public B (A aObj)
{
aObj.TestMethod ();
aObj.bObj.CallMyself ();
}
public void CallMyself()
{
}
}
I want to be able to share only the parts of the project with other people that they are working on. They need to be able to test it out, so they have to compile to project. Is there any magic solution that can be easily automated? The solution should work on any file, I know how to resolve circular dependency with a 3rd assembly.
As I mentioned, I know how to resolve a situation like this. I just wrote a nasty example, to show that I want to create a solution that can deal with any code.
Compile B.dll with class B changed to remove dependency on A
Compile A.DLL with B.dll and class A depending on B
recompile B.DLL with complete class B
If interfaces of classes don't change you may be able to recompile just one without source of another.
Should you go this route - no.
The short answer is don't do this. In this situation, it's common to put common interfaces in a separate library that everyone can see, so they can program to those interfaces without affecting each other, and then put the private stuff in separate assemblies that rely on the first.
E.g.
// myproject.interfaces.dll
interface IA
{
void Process(IB b);
}
interface IB
{
void Process(IA a);
}
// myproject.A.dll - depends on myproject.interfaces.dll
class A : IA
{
....
}
In the following scenario (excuse my pseudocode):
Assembly Lib:
Interface A;
Class 123; //Utilizes multiple properties with a { get; internal set; } pattern.
//Contains more class definitions like Class 123
Assembly Impl: //References Lib
Class MyImpl; //Implements Interface A and utilizes Class 123.
ClientApplication:
//Consumes Interface A
I was wondering if there is a way to allow Class MyImpl to access the property set() of Class 123 without using statically declared friend assemblies and keeping those set() also hidden from the ClientApplication.
The end goal is to be able to deploy this in a manner that allows ClientApplication to utilize the types from AssemblyLib, and being able to drop new implementation assemblies without having to recompile and redistribute Assembly Lib.
I was thinking something along the likes of finding a way to make the internal modifier take effect at its instantiation (Assembly Impl) rather than at its declaration (Assembly Lib) but I dont believe that C# supports anything like this.
I realize this is probably really ugly if it can be done, and I am not sure myself that it can regardless, but alas that is why I am here! Thanks for your help in advance.
You could use reflection to access the internals of Lib. This isn't a very nice solution.
You could make Impl a friend assembly of Lib. This isn't a very nice solution.
You could restructure your design to fix the need for Impl to access Lib's internals. This is the nice solution.
Using your example, here is an idea of what I'm getting at. Why not change the design to:
Assembly Lib:
Interface A;
Interface B; //Utilizes multiple properties with a { get; } pattern.
//Contains more interface definitions like Interface B
Assembly Impl: //References Lib
Class 123; //Utilizes multiple properties with a { get; internal set; }
//pattern. Implements B.
//Contains more class definitions like Class 123
Class MyImpl; //Implements Interface A and utilizes Class 123.
ClientApplication:
//Consumes implementations of Interface A and B provided by Impl.
You might want to look at the InternalsVisibleToAttribute for this.
For example, in your Lib assembly, add this line to your assemblyinfo.cs file:
[assembly:InternalsVisibleTo("Impl")]
How do you solve circular reference problems like Class A has class B as one of its properties, while Class B has Class A as one of its properties?
How to do architect for those kind of problems?
If you take an example of NHibernate, there will be a parent-child relationship between objects.
How is it able to handle those parent child scenarios?
In most cases when I've had to have two things reference each other, I've created an interface to remove the circular reference. For example:
BEFORE
public class Foo
{
Bar myBar;
}
public class Bar
{
Foo myFoo;
}
Dependency graph:
Foo Bar
^ ^
| |
Bar Foo
Foo depends on Bar, but Bar also depends on Foo. If they are in separate assemblies, you will have problems building, particularly if you do a clean rebuild.
AFTER
public interface IBar
{
}
public class Foo
{
IBar myBar;
}
public class Bar : IBar
{
Foo myFoo;
}
Dependency graph:
Foo, IBar IBar
^ ^
| |
Bar Foo
Both Foo and Bar depend on IBar. There is no circular dependency, and if IBar is placed in its own assembly, Foo and Bar being in separate assemblies will no longer be an issue.
I would tell your friend he needs to rethink his design. Circular references like you describe are often a code smell of a design flaw.
Unlike C++ (for instance), C# does not need forward declarations to resolve circular references. Hence:
public class A
{
public B B { get;set; }
}
public class B
{
public A A { get;set; }
}
However, this is often an indicator of questionable design decisions.
In most every case the best solution is to change your design and avoid a circular dependency. For instance you may do one of the following:
Move the common referenced code to a utility project in your solution and have the other projects reference the Utility project
Use an interface as explained by "Ed Bayiates" in his answer.
If its a small amount of simple/common code then rewrite it for one of the classes so you don't need to reference it in a circular dependency. (my least favorite)
However, if you are working in a solution with many projects and you don't have the ability to make one of the changes above because you don't own the code, its to difficult to implement, or not worth the time to fix, then You can use this method:
Right-click on the project references and select "Add Reference...". Then in the dialog window that appears switch to the "Browse" tab and the "Browse" button. From there you can go find the DLL and select it. This is a work around at best and can cause build problems especially if both DLLs are being updated frequently, and/or have many dependencies. I do not recommend this method but it works in a pinch.
Fissh
interfaces are a good idea however if your looking for a quicker solution than redoing the architecture of so many things try building one dll class library that holds all your data structures your main project holds your UI that needs that data and then any other dlls you want to add can access that data structures dll as well so they have all the info they need to run but still can be separate- this is called the tri force design pattern -
Circular reference occurs when two or more interdependent resources cause lock condition. This makes the resource unusable.
To handle the problem of circular references in C#, you should use garbage collection. It detects and collects circular references. The garbage collector begins with local and static and it marks each object that can be reached through their children.
Through this, you can handle the issues with circular references.
Let’s say the following classes is in circular reference. Here both of them depends on each other −
public class A
{
B Two;
}
public class B
{
A one;
}
To solve the issue, create an interface −
public interface myInterface {
}
public class A {
myInterface Two;
}
public class B: myInterface {
A one;
}