Extending multiple/different objects based on required functionality? - c#

Is there a design pattern that allows me to define an object as extending another object depending on the functionality that I need? For example if I have the following classes:
using System;
namespace C_
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("------------------------------------------------");
C c = new C();
Console.WriteLine("------------------------------------------------");
D d = new D();
Console.WriteLine("------------------------------------------------");
}
}
public abstract class A
{
public A() {}
public void DoSomething()
{
Console.WriteLine("Doing something");
}
public virtual void CallSomething()
{
DoSomething();
}
}
public abstract class B : A
{
public B() {}
public override void CallSomething()
{
Console.WriteLine("Do something extra");
DoSomething();
}
}
public class C : A
{
public C()
{
CallSomething();
}
}
public class D : B
{
public D()
{
CallSomething();
}
}
}
Essentially class B is an extension of class A. The minimum functionality I want is defined in class A while in some cases I may need more which is defined in class B. Is it possible to have another class extend either A or B depending on what functionality is required at runtime? I could create separate classes each extending A or B but that would lead to a lot of repeated code
EDIT: Added a more concrete example. Classes C and D have the same functionality except that D requires a little more done before it can proceed hence extending B instead of A. Is there a design pattern where I wouldn't need class D and can pick and choose the functionality of C based on what I need?

Related

Do we really need interfaces for multiple inheritance in c#?

As I was learning about interfaces I came across the fact that they can be used to implement Multiple Interface Inheritance and that Multiple Class Inheritance is not possible in C#. So, I found the following code which implements multiple interface inheritance.
using System;
namespace Test
{
interface IB
{
void PrintB();
}
class A
{
public void PrintA()
{
Console.WriteLine("PrintA() Method.");
}
}
class B : IB
{
public void PrintB()
{
Console.WriteLine("PrintB() Method.");
}
}
class C : A, IB
{
B bObject = new B();
public void PrintB()
{
bObject.PrintB();
}
}
class Program
{
public static void Main()
{
C cObject = new C();
cObject.PrintA();
cObject.PrintB();
}
}
}
But in this code we are inheriting Class A directly. But for inheriting the method of Class B we are using interface IB.
Now, I can't see the advantage of doing so. We could write this code without using interface IB like this.
using System;
namespace Test
{
class A
{
public void PrintA()
{
Console.WriteLine("PrintA() Method.");
}
}
class B
{
public void PrintB()
{
Console.WriteLine("PrintB() Method.");
}
}
class C : A
{
B bObject = new B();
public void PrintB()
{
bObject.PrintB();
}
}
class Program
{
public static void Main()
{
C cObject = new C();
cObject.PrintA();
cObject.PrintB();
}
}
}
Now, why did we used interface in the first place, if we could write it without the interface?
Does this mean multiple inheritance can be done without using interfaces?
Or multiple inheritance cannot be done even using interfaces?
You are missing a point about virtual methods. We want to be able to do this:
interface IPrint
{
void Print();
}
class A : IPrint
{
public void Print()
{
}
}
class B : IPrint
{
public void Print()
{
}
}
...
foreach (IPrint p in printables)
{
p.Print();
}
Your approach cannot do that, because your PrintB in class C is just a method. Inheritance is not about having methods with the same name, but about defining verbs that perform an action on the instance of the class they are designed for.
Multiple Inheritance leads to the Diamond Problem. And that Diamond is a Programmers worst enemy.
So the designers of .NET or the CLI (I can never remember wich) decided they are were not going to deal with that, and mandated "single Inheritance only". Wich is one of the common strategies to deal with that "Diamond of Death".
As only allowing single Inheritance meant somet things would be missing, they Implemented Interfaces to offset it. It is one of the many ways in wich .NET is more restrictive then say Native C++ and had to invent a replacement for something trivial. But in the long run it prooved to be slightly better doing it this way.

How to Access Methods/Interface on Nested Generic Classes

I have need for nesting Generics, as in A< B< Base > > .
When I do this, only the outer properties (A) are exposed. I can not figure out how to access (B)'s methods, etc. I then tried to access the interfaces internally with the same results.
(edit) To clarify the use case, the solution I need should work with
public class C : A < B < Base > > or
public class C : B < A < Base > >
I don't need those to result in identical classes, but both definitions have the corresponding methods. As you might suspect, I am trying to use this to implement common functionality in a modular mode across several objects. Extension methods get me close, but they won't allow overridden behavior as this solution would (if it is achievable).
I have attached test code, which shows the problems perhaps more clearly than I ca.
using System;
using System.Reflection;
namespace ArchitecturalTestGround
{
public interface IBase
{
void BaseMethod1();
}
public interface IA : IBase
{
void AMethod();
}
public interface IB : IBase
{
void BMethod();
}
public class Base : IBase
{
public void BaseMethod1() { }
}
public class A<T> : IA where T : IBase
{
public void BaseMethod1() { }
public void AMethod() { }
}
public class B<T> : IB where T : IBase
{
public void BaseMethod1() { }
public void BMethod() { }
}
public class Test1 : A<B<Base>>
{
}
public class Test2 : B<A<Base>>
{
}
public class Program
{
public static void Main(string[] args)
{
Test1 e1 = new Test1();
Test2 e2 = new Test2();
Console.WriteLine("Test1 - A<B<Base>>");
foreach (MemberInfo mi in typeof(Test1).GetMembers())
{
Console.WriteLine($" {mi.Name}.{mi.MemberType}");
}
if (e1 is IB) { Console.WriteLine(" Supports IB"); }
if (e1 is IA) { Console.WriteLine(" Supports IA"); }
Console.WriteLine();
Console.WriteLine("Test2 - B<A<Base>>");
foreach (MemberInfo mi in typeof(Test2).GetMembers())
{
Console.WriteLine($" {mi.Name}.{mi.MemberType}");
}
if (e2 is IB) { Console.WriteLine(" Supports IB"); }
if (e2 is IA) { Console.WriteLine(" Supports IA"); }
Console.ReadKey();
}
}
}
Test1 is inheriting from A<T> (regardless of what T is) and A<T> inherits from from IA, which in turn inherits from IBase, so you will only see the methods from that inheritance chain:
From A<T>:
public void BaseMethod1() { }
public void AMethod() { }
From IA:
void AMethod();
From IBase:
void BaseMethod1();
(By the way, notice from your code sample that you would probably get a compiler warning because of BaseMethod1).
I think I see where you are going with this. You have probably encountered a situation where you need to inherit from two classes. Multiple class inheritance is not possible in C#. There are some ways around it though.
Generally speaking, if you encounter a situation like this, more times than not it means you need to rethink your design. If you are still interested on the subject, check this guy out:
Multiple Inheritance in C#
Is it possible to change your definitions like this?
public class A<T> : IA where T : IBase
{
T NestedGeneric;
public A(T nested)
{
NestedGeneric = nested;
}
public void BaseMethod1() { }
public void AMethod() { }
}
public class Test1 : A<B<Base>>
{
public B<Base> NestedGeneric;
public Test1(B<Base> nested) : base(nested)
{
NestedGeneric = nested;
}
}
This allows you do do e1.NestedGeneric.BMethod();.

What is the equivalent of C++ Template Inheritance in C#?

I understand this is not possible in C#, because Generics are not Templates and they are implented differently(processing on runtime rather than during compile):
public class Foo<T> : T
{
}
The question though remains. Is there an equivalent or perhaps an alternative way to achieve this?
In my case I have three different parent classes I want to inherit from, let's call them A, B, C:
public class A {}
public class B {}
public class C {}
Then I have the Foo class, and then MANY more inheriting from Foo but each of them needing only one of the A, B, C:
public class X : Foo<A> {}
public class Y : Foo<B> {}
public class Z : Foo<C> {}
So class X needs all the functionality in Foo and all the functionality in A, Y from Foo and B and so on...
How do I do this in C#?
I suppose you cannot modify the A, B and C classes (otherwise you could just inherit all of them from Foo), therefore this is my idea:
I would define "Foo" as an interface (that I would call "IFoo"):
public interface IFoo {}
and implement all its methods as Extension methods:
public static class IFooExtension
{
public static void Method1(this IFoo f) {
// do whatever here;
}
}
then I'd declare the further classe as follow:
public class X : A, IFoo {}
public class Y : B, IFoo {}
public class Z : C, IFoo {}
The only issue (if it is an issue) is that you can implement whatever method you want, but no properties.
If class X: Foo<A> { } needs all the functionality of Foo and A, then simply expose A as property and you will have it:
public class Foo<T> where T : new()
{
public T Bar { get; } = new T();
public void FooMethod() => Console.WriteLine("Foo method");
}
public class A
{
public void AMethod() => Console.WriteLine("A method");
}
public class X : Foo<A>
{
}
class Program
{
static void Main(string[] args)
{
var x = new X();
x.FooMethod();
x.Bar.AMethod(); // access via property
}
}

Can I implement an interface and have it as a field when returning it?

I know it sounds trivial, but is it somehow possible to return the b field when i pass an A variable to a function which expects an IMyIntercace? Then i don't have to implement the Hello() function in the class A, instead i just return b as the IMyInterface.
interface IMyInterface
{
void Hello();
}
class A : IMyInterface
{
B b = new B();
}
class B : IMyInterface
{
public void Hello()
{
Console.WriteLine("Hello");
}
}
class Program
{
static void foo(IMyInterface myInterface)
{
myInterface.Hello();
}
static void Main(string[] args)
{
A someVariable = new A();
foo(someVariable);
}
}
I suppose it cant be done, but is there any design pattern or trick that could do it?
EDIT
The reason i dont want to derive A is because maybe i want to do this
class A : IMyInterface
{
B b = new B();
B b2 = new B();
IMyInterface bPointer;
}
Then i can point to one of the b's depending on some situation
You could inherit A from B.
A will continue to implement the interface and you may override every function you need to change in the future.
interface IMyInterface
{
void Hello();
}
class A : B
{
}
class B : IMyInterface
{
public void Hello()
{
Console.WriteLine("Hello");
}
}
No. Either A implements IMyInterface, in which case you don't need to do anything, or it does not, in which case there is no way to automatically "redirect" any interested parties to the b member.
You can either expose b (and preferably make it a property) to the outside world so that they can refer to it as required, or you can make A implement IMyInterface and manually forward all calls to b like this:
class A : IMyInterface
{
B b = new B();
public void Hello()
{
b.Hello();
}
}
Just make A.b public (or internal) and then call foo(someVariable.b).
What you want to have is interface delegation and unfortunately there is nothing built into the language to help you with that.
Basically, the A class has to implement the interface.
One way it can do that is of course to derive from B:
class A : B
{
}
But if you don't want to do that, then you need to delegate. What you have to do is to implement the delegation yourself so that you can delegate the responsibility of the actual implementation to the B class, you won't get any help from the compiler to fix this.
class A : IMyInterface
{
B b = new B();
public void Hello()
{
b.Hello();
}
}

Is it possible to add methods to classes with PostSharp? If yes, is it possible to then reference those methods from other classes?

Let's say I have a class Abc:
class Abc {
}
and that I'd like to externally add some method m() to it. I guess it's probably possible to do this, although I am not sure how. Assuming it is possible to do that, let's then say Abc does have, from now on, a m() method.
Now, imagine I have other class Def:
class Def {
public void x(Abc abc) {
abc.m();
}
}
Would this code run with PostSharp? To the more distracted reader, the problem with this is that in a standard C# class program, our compiler might not know the Abc class has a m() method.
My gut feeling is that this wouldn't work with PostSharp. Am I mistaken?
(Maybe you can use the DLR to accomplish if my PostSharp solutions aren't sufficient?)
Yes you can. You would use introducemember attribute in an instance scoped aspect. Your best bet is to implement an interface using postshsrp then reference your target class as that interface to expose the method. You can also use Post.Cast<>() to access it at design time.
Here are two methods to do this. The first is via an interface, the second is using stubs.
Method 1 - Interface
public class Program
{
static void Main(string[] args)
{
Customer c = new Customer();
var cc = Post.Cast<Customer, ISomething>(c);
cc.SomeMethod();
}
}
public interface ISomething
{
void SomeMethod();
}
[AddMethodAspect]
public class Customer
{
}
[Serializable]
[IntroduceInterface(typeof(ISomething))]
public class AddMethodAspect : InstanceLevelAspect, ISomething
{
#region ISomething Members
public void SomeMethod()
{
Console.WriteLine("Hello");
}
#endregion
}
Method 2 - stubs
public class Program
{
static void Main(string[] args)
{
Customer c = new Customer();
c.SomeMethod();
}
}
[AddMethodAspect]
public class Customer
{
public void SomeMethod() { }
}
[Serializable]
public class AddMethodAspect : InstanceLevelAspect
{
[IntroduceMember(OverrideAction = MemberOverrideAction.OverrideOrFail)]
public void SomeMethod()
{
Console.WriteLine("Hello");
}
}
More Info
Just in case there are some issues with using the Cast<>() function, it doesn't do an actual cast. The compiled result looks like:
private static void Main(string[] args)
{
Customer c = new Customer();
ISomething cc = c;
cc.SomeMethod();
}
You can do it if the class is in a different assembly.
On the other hand, if the classes are in the same module, then you are right, the C# compiler won't compile it. Why not implement m() like this in C#, then replace the implementation with PostSharp?
class Abc
{
public void m()
{
throw new NotImplementedException ();
}
}
Edit:
What if you put m() in an interface, then use PostSharp to implement the interface on your class? Then you can call the method by casting to that interface.
interface IM
{
void m();
}
class Def {
public void x(Abc abc) {
if (abc is IM)
((IM) abc).m();
}
}

Categories