Nested class written outside of the class - c#

I like using private nested classes, except that they always feel so cluttered. Normally I put them in their own #region, but I would prefer them to be separate from their parent class in terms of location, and I also don't really want them in separate files. What I decided to do was to make their parent class partial, and then to place the child class physically below the parent class in the file.
Unfortunately it seems that you can't have more than one partial class definition per file either.
(EDIT: it turns out you can have more than one partial part per file; it's just the forms designer that doesn't like it.)
What I would really like to do is something like (all in one file):
internal class Parent
{
}
private class Parent.Child1
{
}
private class Parent.Child2
{
}
but it seems like all I can do is either generate a new source file for every new child class, or arrange them like this:
internal class Parent
{
private class Child1
{
}
private class Child2
{
}
}
Is there any way to accomplish what I'm trying to do here?

The closest you can get to this type of encapsulation is using a partial parent class:
internal partial class Parent
{
private Child1 c1Instance = new Child1();
private Child2 c2Instance = new Child2();
}
internal partial class Parent
{
private class Child1
{
}
}
internal partial class Parent
{
private class Child2
{
}
}
You can split these up into multiple files, the end result will be the same - Child1 and Child2 will be private classes internal to Parent and inaccessible elsewhere.
Makes it a bit more confusing sometimes, but I think it's the closest thing to what you are trying to achieve.
Clarification
A C# source file can hold any number of namespaces, and each namespace can contain any number of structs and classes.
This is a valid (but not very functional) C# source file:
using System;
namespace FirstNS
{
public class Class1
{
}
public class Class2
{
}
public partial class Parent1
{
}
public partial class Parent1
{
private class Child1
{
}
private class Child2
{
}
}
}
namespace FirstNS.ChildNS
{
public class Class3
{
}
}
Compiling that gives you the following classes:
FirstNS.Class1
FirstNS.Class2
FirstNS.Parent1
FirstNS.Parent1.Child1 (private)
FirstNS.Parent1.Child2 (private)
FirstNS.ChildNS.Class3
You could also split each of the class definitions above into multiple files, if you have a reason to do so.

Related

C# - using namespace across files within a shared namespace

I have a namespace that will change somewhat frequently in my project (each product generation) and would like to keep references to that specific namespace contained to the file where I define a base class. In other files I define child classes that usually can get by with getting references to the namespace by inheritance, but I am having trouble with one case as the objects are very specific and I would prefer to link to the namespace within the base class rather than each object.
BaseClass.cs
namespace CommonNameSpace
{
using _productSpecificNameSpace;
_productSpecificNameSpace.thing.otherthing thingotherthingGood = _productSpecificNameSpace.thing.otherthing.Success;
_productSpecificNameSpace.thing.otherthing thingotherthingBad = _productSpecificNameSpace.thing.otherthing.SpecificFailure;
public class BaseClass
{
}
}
SubClass.cs
namespace CommonNameSpace
{
public class SubClass : BaseClass
{
var yeaOrNeigh = thingotherthingGood
}
}
How can I access _productSpecificNameSpace in SubClass.cs without having to call it _productSpecificNameSpace in each subclass, or name every possible object that I will need in BaseClass? Is there a way to get an alias to a namespace attached to a class for inheriting?
Edit: Ideally, I would like to have access to the data types in the interchangeable namespace, as it is mostly a library of enums. Wouldn't having an interface replace the type of these enums with an interface type that would be incomparable with calls to APIs expecting the underlying type?
If you use an interface, you can then instantiate the generation you want to at runtime, without affecting any existing code:
interface IMyThing
{
void DoStuff()
}
abstract class BaseThing : IMyThing
{
public virtual void DoStuff()
}
Generation1:
class MyGen1 : BaseThing
{
public override void DoStuff()
{
// I'm Gen 1
}
}
Generation2:
class MyGen2 : BaseThing
{
public override void DoStuff()
{
// I'm Gen 2
}
}

Using generic base class for WPF window

Why is this:
public abstract class WindowControls<T> : Window
not possible. I can't seem to figure it out.
public partial class AnglesteelWindow : WindowControls<AngleSteel> {
private UCListView uc;
public AnglesteelWindow() {
InitializeComponent();
uc = new UCListView();
uc.SubmitClick += new EventHandler(ButtonPressed);
this.uc.grid.PreviewMouseLeftButtonUp +=
new System.Windows.Input.MouseButtonEventHandler(
this.MousePressed14<AngleSteel>);
stkTest.Children.Add(uc);
uc.amountLabel.Content = "Milimeter";
uc.grid.ItemsSource = DatabaseLogic.MaterialTable("Anglesteel").DefaultView;
base.Material(uc, "Anglesteel");
}
}
I know how generics work, but don't know why it is not possible to make my AnglesteelWindow derive from WindowControls.
The error it gives me is the following:
Base class of 'Name of the solution' differs from declared in other parts.
When i look at the so called other part it is the following:
public partial class AnglesteelWindow :
WindowControls<AngleSteel> System.Windows.Markup.IComponentConnector {
This is made in the AnglesteelWindow.g.i.cs file. If i remove it from there it makes no difference at all.
Adding on #MichaelMairegger answer, you can reach your goal by creating another non-generic class that inherits from the generic class like this:
public abstract class WindowControlsOfAngleSteel : WindowControls<AngleSteel>
{
}
And make your window class inherit from it like this:
From XAML:
<ns:WindowControlsOfAngleSteel >
</ns:WindowControlsOfAngleSteel >
Where ns is the namespace where WindowControlsOfAngleSteel exists.
In code (optional):
public partial class AnglesteelWindow : WindowControlsOfAngleSteel
{
}
You cannot change the inheritance tree. AnglesteelWindow is partial because it is also declared in AnglesteelWindow.xaml where the root element is Window. If you want to inherit from another class you have to replace there the Window root by your base class.
public class MyDerivedBaseWindow : Window {}
<ns:MyDerivedBaseWindow >
<!-- WindowContent-->
</ns:MyDerivedBaseWindow >
But you cannot use a Generic class in XAML. You have to change your logic that the base-window-class that you want to use as window-root is non-generic.

How to get access to a subclass when the other class only knows the superclass?

I have a C# Windows Forms Application form1.cs with a Class Library (DLL) called class1.cs. Now on the UI side I do the following:
using System;
...
using System.Windows.Forms;
using ClassLibrary1;
namespace UI
{
public partial class Form1 : Form
{
MyLibraryClass mlc = null;
public Form1()
{
InitializeComponent();
mlc = new MyLibraryClass(this);
}
public void aMethod() {
Console.Write("Test");
}
}
}
In the Class Library I take the Form reference and want to call the method within, but I don't have access to it:
...
using System.Windows.Forms;
namespace ClassLibrary1
{
public class MyLibraryClass
{
private Form _form;
public MyLibraryClass(Form form)
{
this._form = form;
this._form.aMethod(); //Not working!
}
}
}
The reason as I understand it is that my ClassLibrary1 only knows Form but not Form1 and hence cannot call methods from Form1. The problem is, the UI knows the Class Library but not the other way around, since that would create a ring dependency as you certainly know. But how can I solve this problem?
Instead depeding of Form you can create an interface.
public interface IMyInterface {
void aMethod();
}
Form1 will implement the interface we created
public partial class Form1 : Form, IMyInterface
{
MyLibraryClass mlc = null;
public Form1()
{
InitializeComponent();
mlc = new MyLibraryClass(this);
}
public void aMethod() {
Console.Write("Test");
}
}
In MyLibraryClass now you will depend on the interface not the form. This way MyLibraryClass can use any form that respect the contract and we make sure that in MyClassLibrary will never be passed any intruder form.
public class MyLibraryClass
{
private IMyInterface _form;
public MyLibraryClass(IMyInterface form)
{
this._form = form;
this._form.aMethod(); // now is work :)
}
}
Notes:
The interface will be created in Class Library project (where MyClassLibrary is created).
I recommend you to take a look on SOLID principles.
Circular dependencies are something you will want to avoid whenever possible, but let's assume you still need this.
The easiest solution would be to put the MyLibraryClass and Form1 in the namespace, so you can replace the Form type parameter with a Form1. If you want to keep things nicely separate however, you will have to add a new type.
In you library you would have to add an interface that contains that method.
public interface IMyInterface
{
void aMethod();
}
If you then change the parameter to an IMyInterface instead, you have access to that method. If you need access to normal Form methods or the aMethod is always the same, you could opt for an abstract class that inherits from Form too.
Depend upon Abstractions. Do not depend upon concretions
public interface IMethod
{
void aMethod();
}
public partial class Form1 : Form,IMethod
public MyLibraryClass(IMethod form)
{
this._form = form;
this._form.aMethod();
}
If you can, you should enforce statically the Form1 class in the argument list:
public MyLibraryClass(Form1 form)
{
// ...
}
If you cannot (which is often the case when several assemblies are used) you should test and cast dynamically:
public MyLibraryClass(Form form)
{
if (form is Form1)
{
(form as Form1).aMethod();
}
}
BUT YOU REALLY SHOULD honor the DIP (Dependency inversion principle), instead: depend from abstractions. Implement an interface and depend from that instead of Form1.
But if you've had the issue in the first place, you probably haven't cleared out for yourself how dependencies are organized between assemblies or, worse, don't know exactly why some answers propose to use interfaces.
Read the link above to know more about why, because your problem really is not about HOW but WHY.

Share properties among several user controls

I have several UserControls that are sharing some common properties. Example:
private List<MyObject> Sample
{
get
{
return Session["MyObject"] as List<MyObject>;
}
set
{
Session["MyObject"] = value;
}
}
I want to share this to all user controls inside my project. (Not to other projects in a solution, of course). What I'm trying to do is create a separate class and inherit from that class. Something like:
public class SampleBase : Web.UI.UserControl
{
protected List<MyObject> Sample
{
get
{
return Session["MyObject"] as List<MyObject>;
}
set
{
Session["MyObject"] = value;
}
}
}
And then my control can inherit those values by deriving from that class:
partial class myControl : SampleBase
One problem I encounter is that I cannot derive from base if control already has something inherited:
partial class myControl : SomethingELSE
Otherwise it works fine, but I'm not sure if it is a good approach and I'm looking for suggestions.
If my understanding is correct, you only want to get rid of the inheritance hierarchy of your User Controls
Another approach would be using Extension Methods
For example:
Interface to mark your USerControls
public interface IMyUserControlMark { }
Extensions
public static class MyUserClassExtensions
{
public static List<object> GetSampleData(this IMyUserControlMark myUserControl)
{
if (HttpContext.Current.Session["MyObject"] == null)
{
return Enumerable.Empty<object>().ToList();
}
return HttpContext.Current.Session["MyObject"] as List<object>;
}
public static void SetSampleData(this IMyUserControlMark myUserControl, List<object> myObject)
{
HttpContext.Current.Session["MyObject"] = myObject;
}
}
User control
public partial class Content1 : System.Web.UI.UserControl, IMyUserControlMark
{
...
}
public partial class Content2 : System.Web.UI.UserControl, IMyUserControlMark
{
....
}
Now you will be able to call your extension methods from within your UserControl or from the ASPX code behind like this:
From the UserControl
var myObject = this.GetSampleData();
this.SetSampleData(myObject);
From the ASPX code behind
var myObject = this.uc1.GetSampleData();
this.uc1.SetSampleData(myObject);
This is a classic example where you need to "favor composition over inheritance".
Instead of inheriting from the class, you hold a reference to an instance of the class. Then you provide simple pass-through code to access the methods/properties of the class.
So, for your example:
public class SomeBehavior
{
public List<MyObject> Sample
{
get { return Session["MyObject"] as List<MyObject>; }
set { Session["MyObject"] = value; }
}
}
public class MyControl : UserControl
{
private SomeBehavior _someBehavior;
public MyControl()
{
_someBehavior = new SomeBehavior();
}
public List<MyObject> Sample
{
get { return _someBehavior.Sample; }
set { _someBehavior.Sample = value; }
}
}
Another option is to allow access to the behavior class directly:
public class MyControl : UserControl
{
public SomeBehavior SomeBehavior { get; private set; }
public MyControl()
{
SomeBehavior = new SomeBehavior();
}
}
The advantage of this is that you don't have to write the pass-through code. The disadvantage is that it violates the Law of Demeter, which says that you should "only talk to your immediate friends". If you do it this way, other classes that use MyControl need to know about SomeBehavior. Following the Law Of Demeter can improve maintainability and adaptability of your code, but it comes at a cost of lots of pass-through code.
Apart from previous solutions, maybe it's time for applying some MVC/MVP pattern?
For web forms there is a great framework called WebFormsMVP: link
In the library there is a mechanism called Cross Presenter Messaging thanks to which you can share a data between your controls using the publish/subscribe pattern.
For better explanation look here and here
I suggest to give the library a chance :)
In C# you can inherit from only one class and implement multiple interfaces.
This is allowed:
partial class myControl : SampleBase
partial class myControl : SampleBase, Interface1
partial class myControl : SampleBase, Interface1, Interface2, Interface3
This is NOT allowed:
partial class myControl : SomethingELSE, SampleBase
Try making SomethingELSE inherit from SampleBase if it satisfies your design. If not, then I suggest encapsulating SampleBase as a property of each control that needs it as it also suggested #DanM.

Dividing class file into partial classes affects scope?

I have a class library project, and my namespace/main class looks like this:
File: Document.cs
namespace HtmlEngine
{
public class Document : IDisposable
{ ...
public class DocumentActionReplaceByTag : IDocumentAction
{
All of this works fine, and in another project/assembly I put:
using HtmlEngine;
...
DocumentActionReplaceByTag currentDocAction = new HtmlEngine.DocumentActionReplaceByTag("[NEXT_PART]");
and it works perfectly. However, I've now divided that Document class file into several files, called DocumentActions.cs, DocumentSections.cs, as well as keeping the main functionality in my Document.cs file. At the top of each of these I put:
public partial class Document : IDisposable
{
Now, in the consuming project I get a 'cannot resolve symbol 'DocumentActionReplaceByTag'' error. I still have my using reference to HtmlEngine.
The closest thing on the 'net I could find was this post which describes my plight similarly, but he wasn't very clear about the reasons for it happening: http://www.daniweb.com/software-development/csharp/threads/140673/understanding-partial-classes
I have always believed partial classes were syntactic sugar and they were combined into a single class prior to compilation. I repeated the interface for each partial class declaration, not sure if that could be a factor.
Why would this now be out of scope?
If I understood your code correctrly the line for creating new DocumentActionReplaceByTag must look like:
DocumentActionReplaceByTag currentDocAction = new HtmlEngine.Document.DocumentActionReplaceByTag("[NEXT_PART]");
And what about IDisposable, it must be specified only in one partial file.
Glinkot, from provided code I see that your DocumentActionReplaceByTag class is put into Document class. The folowing sample shows that Nested classes always accessable via ParentClass.NestedClass (note that all my classes are in same file and code not compiles)
namespace SomeNamespace
{
public class ParentClass
{
public class NestedClass { }
public void SomeMethod()
{
// This compiles, since nested class is used inside parent class
NestedClass nestedClass = new NestedClass();
}
}
public class AnotherClass
{
public AnotherClass()
{
// Not compiles since "NestedClass" is defined as nested class
var nestedClass = new NestedClass();
// Will compiles
var nestedClass = new ParentClass.NestedClass();
// Not compiles since "NestedClass" is defined as nested class
NestedClass nestedClass = new NestedClass();
// Will compiles
ParentClass.NestedClass nestedClass = new ParentClass.NestedClass();
}
}
}
If you have another situation then please provide more details.

Categories

Resources