How to include the methods from on class in another - c#

I want to me able to include a bunch of methods from one main class into several Forms.
Example
class Master{
public void kill(){
this.Hide()
}
}
class b : Form{
//What must I do so that class 'b' can call kill, an it would mean that b would close
}
First i thought if Master inherits Form, then b can inherit Master, but that failed. Not a clue, really struggling, all comments welcome. Thank you!
Edit
Ok, there are lots of functions and variables which need to be copied into the form. This is why i wanted something similar to sub classing.

Make kill into an extension method.
public static class FormExtensions
{
public static void Kill(this Form form)
{
...
}
}
Or if you don't want it to apply to every form, then you can extend a marker interface and apply it to the applicable forms
public interface IKillable
{ }
public static class KillableExtensions
{
public static void Kill(this IKillable form)
{
...
}
}

make a master and call it
class b : Form{
//What must i do so that class be can call kill
Master _master = new Master();
void Stuff()
{
_master.kill();
}
}
You can also make extension methods.... assuming there is no members of Master that you want to access
Or you could make Master inherit Form, then make b inherit Master

You can call a method from other class by creating its object.
EXAMPLE:
public class A
{
public void myMethod()
{
}
}
public class B
{
A a = new A(); // here 'a' is an object of class 'A'
a.myMethod();
}

Related

C# WinForms 'this.Controls.Find' in a separate class

I am trying to divide my program into classes to reduce clutter and increase readability.
In one of my methods, I need to find the location of a label on the screen.
this.Controls.Find worked before I moved everything into separate classes but it doesn't exist anymore because I am no longer executing it in the same class as the controls. I tried Main.Controls.Find (Main.cs is where my form is executed and set out) but this also didn't work and I got the error, "An object reference is required for the non-static field, method, or property 'Control.Controls'"
How do I reference the controls? Do I need to add an additional using statement?
Thanks,
Josh
You need a reference to the form, passed down to the newly introduced method (or class).
Before
public class Main : Form {
public void Whatever() {
...
this.Controls.Find(...);
}
}
After
public class Main : Form {
public void Whatever() {
...
new Helpers().HelperMethod( this );
}
}
public class Helpers {
public void HelperMethod( Form form ) {
...
form.Controls.Find
}
}
or
public class Main : Form {
public void Whatever() {
...
new Helpers( this ).HelperMethod();
}
}
public class Helpers {
private Form Form { get; set; }
public Helpers( Form form ) {
this.Form = form;
}
public void HelperMethod() {
...
this.Form.Controls.Find
}
}

Communicating both ways between classes

A little background on my project:
I'm making a multi-form application, which consists of 1 mainform, and 6 childforms that can be called from the mainform, but only 1 childform can be active at a time. These childforms share certain parts of code, which I do not want to copy. To solve this, I have a codefile within the same namespace which holds the nessaccary code.
This codefile however, needs access to certain properties of the currently active childform.
My search has come down to using an interface to extract the needed information from the active childform.
My code is currently looking like this:
Interface:
public interface Interface1
{
TabControl tabControl_Buizen_
{
get;
}
TabPage tabPage_plus_
{
get;
}
}
Childform:
public partial class Childform : Form, Interface1
{
Interface1 dummy;
public TabControl tabControl_Buizen_
{
get { return this.tabControl_Buizen; }
}
public TabPage tabPage_plus_
{
get { return this.tabPage_plus; }
}
Methods_newTabPage methods = new Methods_newTabPage(dummy);
}
Codefile:
public class Methods_newTabPage
{
private readonly Interface1 form;
public Methods_newTabPage(Interface1 formInterface)
{
this.form = formInterface;
}
}
As you can see I'm using Methods_newTabPage methods = new Methods_newTabPage(dummy); to be able to call methods in my codefile, but the codefile requires the interface to be passed (which I filled as "dummy"). This however pops the error "A field initializer cannot reference the non-static field, method, or property Childform.dummy".
How can I let the childforms access the methods in the codefile, while also giving the codefile access to certain controls in differing childforms?
The error is easy to fix: just make dummy static.
static Interface1 dummy;
However, I don't think that will help you much. Why are you passing this dummy to Methods_newTabPage anyway? This will lead to NullReferenceExceptions inside the code file because dummy was never initialized with anything.
Don't you rather want to pass this, i.e. the current instance of Childform?
But you cannot just exchange dummy with this like so:
// Compiler error "Keyword 'this' is not available in the current context".
Methods_newTabPage methods = new Methods_newTabPage(this);
Instead you have to add a constructor that creates Methods_newTabPage:
public partial class Childform : Form, Interface1
{
private Methods_newTabPage methods;
public Childform()
{
methods = new Methods_newTabPage(this);
}
public TabControl tabControl_Buizen_ { get { return this.tabControl_Buizen; } }
public TabPage tabPage_plus_ { get { return this.tabPage_plus; } }
}
Try adding a constructor that initializes the field methods.
Also I don't see how that dummy makes sense. Instead initialize methods via methods = new Methods_newTabPage(this); in the constructor.

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.

limit method to only be called by a particular class

I want a particular method in one class to only be accessible by a particular class. For example:
public class A
{
public void LimitedAccess() {}
public void FullAccess() {}
}
public class B
{
public void Func()
{
A a = new A();
a.LimitedAccess(); // want to be able to call this only from class B
}
}
public class C
{
public void Func()
{
A a = new A();
a.FullAccess(); // want to be able to call this method
a.LimitedAccess(); // but want this to fail compile
}
}
Is there is a keyword or attribute that I can use to enforce this?
UPDATE:
Due to existing system complexity and time constraints, I needed a low impact solution. And I wanted something to indicate at compile time that LimitedAccess() could not be used. I trust Jon Skeet's answer that exactly what I had asked for could not be done in C#.
The question and Jon's answer are good for those who may run across this later. And the fact that this design smells can hopefully veer anyone away for choosing something like this as a desired a solution.
As mentioned in a comment, the C# friend conversation is useful reading if you are trying to solve a similar situation.
As for my particular solution: "why would A contain B's logic" (asked by #sysexpand in comments). That's the rub. B.Func() was called throughout the system I'm working on, but it primarily operated on a singleton of A. So what I ended up doing was moving B's Func() into A and making A.LimitedAccess() private. There were a few other details to work around, as there always are, but I got a low impact solution that gave me compile-time errors on callers to A.LimitedAccess().
Thanks for the discussion.
No. The only thing you could do would be to make LimitedAccess a private method, and nest class B within class A.
(I'm assuming you want all the classes in the same assembly. Otherwise you could put A and B in the same assembly, and C in a different assembly, and make LimitedAccess an internal method.)
Yes. What you are asking for is perfectly possible.
You can restrict access to methods and variables for a specific instance, by using an interface.
However, an interface alone cannot prevent someone from creating their own instance of the class, at which point they will have full access to that instance.
To do that, next you should nest it as a private class inside of another class in order to restrict access to the constructor.
Now you have a particular method in one class to only be accessible by a particular class.
In this example, only class B is ever able to access function LimitedAccess.
public interface IA
{
void FullAccess();
}
public class B
{
private class A : IA
{
public void LimitedAccess() {} //does not implement any interface
public void FullAccess() {} //implements interface
}
private A a = new A();
public IA GetA()
{
return (IA)a;
}
public void Func()
{
/* will be able to call LimitedAccess only from class B,
as long as everybody else only has a reference to the interface (IA). */
a.LimitedAccess();
}
}
//This represents all other classes
public class C
{
public void Func(IA ia)
{
ia.FullAccess(); // will be able to call this method
ia.LimitedAccess(); // this will fail to compile
}
}
public static class MainClass
{
public static void Main(string[] args)
{
B b = new B();
b.Func();
IA ia = b.GetA();
C c = new C();
c.Func(ia);
}
}
In case you just want to remind yourself (or team mates) to not call LimitedAccess everywhere, you could consider using explicit interface implementation or mark LimitedAccess as obsolete.
public interface IA
{
void LimitedAccess();
void FullAccess();
}
public class A : IA
{
private void LimitedAccess() { }
public void FullAccess() { }
void IA.LimitedAccess() => LimitedAccess();
void IA.FullAccess() => FullAccess();
}
public class B
{
public void Func()
{
IA a = new A();
a.LimitedAccess(); // want to be able to call this only from class B
}
}
public class C
{
public void Func()
{
A a = new A();
a.FullAccess(); // want to be able to call this method
a.LimitedAccess(); // -> fails to compile
}
}
Maybe this is a workaround.
Use the System.Runtime.CompilerServices and then you can either check the Name of the calling function and/or the file, in which the calling function is defined. If you have a class per file, the filename might be a substitude for the class name. Check it and block the call.
internal void MySecretFunction (string something,
[CallerMemberName] string memberName = null,
[CallerFilePath] string filePath = null,
[CallerLineNumber] int lineNumber = 0) {
if (!filePath.EndsWith(#"\goodClass.cs")) return;
// else do something
}
You could always see the calling type with a StackTrace.
Just note that when building in release mode, the call on the stack will get optimized, and its possible that the stack trace could return a completely different class, so just make sure to test it before you publish.
/// <summary>
/// Warning: Any class that calls this other than "B" will throw an exception.
/// </summary>
public void LimitedAccess()
{
if (new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().DeclaringType != typeof(B)) throw new Exception("Invalid Caller Type, B is only class able to call this method.");
}
Unfortunately you wont be able to know if its an error on compile time. Best you can do is throw an exception if it gets called, and add a comment warning people about it.
It is against OOP best practices to make such a design. Methods of classes are not supposed to be protected from being called.
If your design requires control over calling a method, then control should be exercised by testing the arguments - caller which is authorized to make a call would "know" the magic word to pass as the argument.
This is a variation of the solution suggested by #cowlinator using class AWithUnlimitedAccess derived from class A rather than class A implementing interface IA.
The result and the limitations are the same, but I like it better because (1) the limited access methods are defined inside its own class and (2) it's easier to add documentation comments.
public class A
{
public void FullAccess() { }
}
public class AWithUnlimitedAccess : A
{
public void LimitedAccess() { }
}
public class B
{
private AWithUnlimitedAccess a = new AWithUnlimitedAccess();
public A GetA()
{
return a;
}
public void Func()
{
a.FullAccess();
a.LimitedAccess();
}
}
// This represents all other classes
public class C
{
public A A;
public void Func()
{
A.FullAccess();
A.LimitedAccess(); // this will fail compile
}
}
public static class MainClass
{
static void Main(string[] args)
{
B b = new B();
b.Func();
C c = new C();
c.A = b.GetA();
c.Func();
}
}

C# - using polymorphism in classes I didn't write

What is the best way to implement polymorphic behavior in classes that I can't modify? I currently have some code like:
if(obj is ClassA) {
// ...
} else if(obj is ClassB) {
// ...
} else if ...
The obvious answer is to add a virtual method to the base class, but unfortunately the code is in a different assembly and I can't modify it. Is there a better way to handle this than the ugly and slow code above?
Hmmm... seems more suited to Adapter.
public interface ITheInterfaceYouNeed
{
void DoWhatYouWant();
}
public class MyA : ITheInterfaceYouNeed
{
protected ClassA _actualA;
public MyA( ClassA actualA )
{
_actualA = actualA;
}
public void DoWhatYouWant()
{
_actualA.DoWhatADoes();
}
}
public class MyB : ITheInterfaceYouNeed
{
protected ClassB _actualB;
public MyB( ClassB actualB )
{
_actualB = actualB;
}
public void DoWhatYouWant()
{
_actualB.DoWhatBDoes();
}
}
Seems like a lot of code, but it will make the client code a lot closer to what you want. Plus it'll give you a chance to think about what interface you're actually using.
Check out the Visitor pattern. This lets you come close to adding virtual methods to a class without changing the class. You need to use an extension method with a dynamic cast if the base class you're working with doesn't have a Visit method. Here's some sample code:
public class Main
{
public static void Example()
{
Base a = new GirlChild();
var v = new Visitor();
a.Visit(v);
}
}
static class Ext
{
public static void Visit(this object b, Visitor v)
{
((dynamic)v).Visit((dynamic)b);
}
}
public class Visitor
{
public void Visit(Base b)
{
throw new NotImplementedException();
}
public void Visit(BoyChild b)
{
Console.WriteLine("It's a boy!");
}
public void Visit(GirlChild g)
{
Console.WriteLine("It's a girl!");
}
}
//Below this line are the classes you don't have to change.
public class Base
{
}
public class BoyChild : Base
{
}
public class GirlChild : Base
{
}
I would say that the standard approach here is to wrap the class you want to "inherit" as a protected instance variable and then emulate all the non-private members (method/properties/events/etc.) of the wrapped class in your container class. You can then mark this class and its appropiate members as virtual so that you can use standard polymorphism features with it.
Here's an example of what I mean. ClosedClass is the class contained in the assembly whose code to which you have no access.
public virtual class WrapperClass : IClosedClassInterface1, IClosedClassInterface2
{
protected ClosedClass object;
public ClosedClass()
{
object = new ClosedClass();
}
public void Method1()
{
object.Method1();
}
public void Method2()
{
object.Method2();
}
}
If whatever assembly you are referencing were designed well, then all the types/members that you might ever want to access would be marked appropiately (abstract, virtual, sealed), but indeed this is unfortunately not the case (sometimes you can even experienced this issue with the Base Class Library). In my opinion, the wrapper class is the way to go here. It does have its benefits (even when the class from which you want to derive is inheritable), namely removing/changing the modifier of methods you don't want the user of your class to have access to. The ReadOnlyCollection<T> in the BCL is a pretty good example of this.
Take a look at the Decorator pattern. Noldorin actually explained it without giving the name of the pattern.
Decorator is the way of extending behavior without inheriting. The only thing I would change in Noldorin's code is the fact that the constructor should receive an instance of the object you are decorating.
Extension methods provide an easy way to add additional method signatures to existing classes. This requires the 3.5 framework.
Create a static utility class and add something like this:
public static void DoSomething(this ClassA obj, int param1, string param2)
{
//do something
}
Add a reference to the utility class on the page, and this method will appear as a member of ClassA. You can overload existing methods or create new ones this way.

Categories

Resources