How to go about an 'overridable' method in an interface driven plugin - c#

I have an app that accepts plugins using a shared library full of interface classes, but would also like to define some static methods to interact with them that can be overridden by the plugin. I understand the limitations in C# that preclude me from just defining the 'override-able' virtual method as static, but need to know what approach to take nonetheless.
And before anybody marks this as duplicates of 'Declare virtual inside static' questions, I have read all that I can find and none show a workaround for achieving the same results especially considering that I am using interfaces.
public interface IMyClass
{
int MyNum {get;}
}
public static class Extensions
{
public static int NewMyNum(this IMyClass class)
{
return class.MyNum * 2;
}
}
public class FirstClass : IMyClass
{
int MyNum {get {return 5;}}
}
public class AnotherClass : IMyClass
{
int MyNum {get {return 5;}}
public override NewMyNum(this IMyClass class)
{
return class.MyNum * 3;
}
}
public class Main()
{
IMyClass AClassObj = new IMyClass();
console.writeLine(AClassObj.NewMyNum());
IMyClass BClassObj = new IMyClass();
console.writeLine(BClassObj.NewMyNum());
}
I know this is nowhere near compile-able code, but I hope it illustrates what I am trying to achieve without me posting hundreds of line of code.

Related

Can't get C# default interface method to compile

C# 8.0 has a new feature that lets you add a default implementation to a method on an interface. Either I'm doing something wrong or this feature doesn't work as advertised. (I'm guessing it's the former.)
I created a new .NET Core 3.1 console app with the following code:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var xxx = new MyClass { MyInt = 5 };
Console.WriteLine(xxx.GetItNow());
}
}
public interface ITest
{
int MyInt { get; set; }
int GetItNow() => MyInt * 2;
}
public class MyClass : ITest
{
public int MyInt { get; set; }
}
}
The Console.WriteLine(xxx.GetItNow())); statement doesn't compile because
Myclass does not contain a definition for 'GetItNow()'...
So, the compiler is happy with the fact that MyClass doesn't explicitly reference GetItNow() (it doesn't complain the MyClass doesn't implement the interface). But it doesn't see the default interface member as a public method of the class that implements the interface.
Am I missing something, or is something broken?
Well, interface default method belongs to the interface not to a class which implements it; so you have two possibilities:
Cast:
Console.WriteLine(((ITest)xxx).GetItNow()));
Declaration change (preferable; MyClass is implementation detail, often it's a dependency; ITest - contract is the only thing which matter):
ITest xxx = new MyClass { MyInt = 5 };
// xxx is ITest, so xxx.GetItNow() is legal now
Console.WriteLine(xxx.GetItNow());
https://stackoverflow.com/a/61717913/779967 is excellent and clear answer, I was trying to do the same with this new feature but got stopped by the compiler. Now I know why.
If your intention is to mark some class with an interface and get some functionality attached to it. I’ve been using extension methods on the interface itself to achieve this effect. The only downside is that only functions are supported at this time not properties.
public interface ITest
{
int MyInt { get; set; }
}
public static class ITestExtensions
{
public static int GetItNow(this ITest self)
{
return self.MyInt * 2;
}
}

C# access children's static member in parent

I have a class Foo, which is a base class for a lot other classes such as Bar and Baz, and I want to do some calculation within Foo using the static members in Bar and Baz, as shown below:
public class Foo{
public result1 {
get{
return field1;
}
}
}
public class Bar : Foo{
public const int field1 = 5;
}
public class Baz : Foo{
public const int field1 = 10;
}
The only solution I can think of is wrap all the fields in a container, add an extra identifier for each object, and use a function to return the fields, like so
Bar : Foo{
public readonly int id = 0;
public static Wrapper wrapper;
}
public Wrapper GetWrapper(int id){
switch(id){
case 0:
return Bar.wrapper;
}
}
However, as you can see, I need to maintain one additional class and function, and I'd rather not to fragment my code. Is there any alternative?
Edit
What you are asking for, i.e. accessing a static or const value in a subclass from a base class is technically possible, but doing so will violate the principals of good SOLID OO design. Also, since you will need an instance of a specific subclass in order to be able to 'reason over' the type of the subclass in order to obtain the appropriate field1, there's little point approaching this problem statically.
Instead, the common, cleaner, approach here is to use subtype polymorphicism which will allow a calling method in the base class, or a method in an external class altogether, to access the appropriate value for 'field1' based on the subclass. This allows control over the value returned to remain inside the appropriate subclasses (i.e. as per your words, the code won't become "fragmented").
Alternative solution using subclass polymorphicism (recommended)
A subclass polymorphic approach (i.e. with the virtual/abstract and override keywords) will allow you to encapsulate the retrieval of a value (or object) which is customizable for each subclass. Here, the abstraction remains conceptually at "give me an integer value", and then the sub-class-specific implementations of 'how' to return the value can be abstracted (hidden) from the caller. Also, by marking the base property as abstract, you will force all subclasses to implement the property, so that the requirement to provide a value isn't forgotten about.
i.e. I would recommend a polymorphic approach like this:
public abstract class Foo
{
public abstract int Result { get; }
}
public class Bar : Foo
{
// This is implementation specific. Hide it.
private const int field1 = 5;
public override int Result
{
get { return field1; }
}
}
public class Baz : Foo
{
public override int Result
{
// No need for this implementation to be a constant ...
get { return TheResultOfAReallyComplexCalculationHere(); }
}
}
If there are no other reusable concrete methods on the base class Foo, then you could also model the abstraction as an interface, with the same effect:
public interface IFoo
{
int Result { get; }
}
Approaching this problem without polymorphicism (Not recommended)
Any compile-time attempt to access static fields on subclasses will typically require code somewhere to switch (or map) on the actually type of the subclass instance, e.g.:
public class Foo
{
public int result1
{
get
{
switch(this.GetType().Name)
{
case "Bar":
return Bar.field1;
case "Baz":
return Baz.field1;
default:
return 0;
}
}
}
public void MethodRequiringValueFromSubclass()
{
Console.WriteLine(result1);
}
}
public class Bar : Foo
{
public const int field1 = 5;
}
public class Baz : Foo
{
public const int field1 = 10;
}
The problem here is that the Open and Closed principal is violated, as each time a new sub class is added, the result1 method would need to be changed to accomodate the new class.
I'd suggest to use abstract function rather that using static member.
public abstract class Foo{
public result1 {
get{
return get_field1();
}
}
protected abstract int get_field1();
}
public class Bar : Foo{
public const int field1 = 5;
protected override int get_field1() { return field1;}
}
public class Baz : Foo{
public const int field1 = 10;
protected override int get_field1() { return field1;}
}
You either add constructor parameter to your Foo class which can be passed from inheritors, thus you don't need extra classes also you'll have less coupling
public class Foo
{
private readonly int _field1;
public Foo(int field1)
{
_field1 = field1;
}
}
or you can use it exactly from inheritors type as static/const members are members of class type
public class Foo
{
public result1
{
get
{
return Bar.field1;
}
}
}
but this gives your code less flexibility and more coupling.
Also you have an option by using virtual properties which you can implement in derrived classes and use in base:
public class Foo
{
public virtual int Field { get { return 0; } }
}
Instead of making Foo abstract as other answers suggested you can use virtual and override result1 in each child class
public class Foo
{
public virtual int result1 { get; }
}
public class Bar : Foo
{
public const int field1 = 5;
public override int result1
{
get { return field1; }
}
}
public class Baz : Foo
{
public const int field1 = 10;
public override int result1
{
get { return field1; }
}
}
If you want default result1 to return something else than 0 you can give it another value
public class Foo
{
public virtual int result1 { get; } = -1;
}
I always feel like a jerk when I answer my own question... Yet didn't see what I was expecting so I might as well just share what I've got after a night of mind boggling.
The reason I don't want to make the calculation abstract/virtual is because there are many subclasses and the formula is the same for all of them. I just refuse to type the same code 10-20 times repeatedly.
Couldn't make the static fields non static either, as they should be accessible at a class level plus they can get big, and they are the same for all instances.
The only solution I can come up that minimizes code fragment is something like this
public class Foo {
public class Wrapper {
Fields...
}
public Wrapper wrapper; // reference
public int result1 { get; }
}
public class Bar : Foo {
public static Wrapper subclassWrapper; // put in the implementation
public Bar() : base(){
wrapper = subclassWrapper;
}
}
So each instance now needs to hold an extra reference, however I don't need to keep a function. The wrapper is kept within the base class so it is less fragmented.

C# Way to enforce all classes have a method of a given name

I am not sure if this even makes sense hence asking it widely.
Is it possible for enforce that a set of classes always implements a function with a given name. The method in each class might have different signature - but should have the same name. Some like below:
public class ClassOne {
public int GetSomething (int a, int b, out int c) { }
}
public class ClassTwo {
public int GetSomething ( int a, out string b) {}
}
I want anyone who writes ClassThree or ClassFour as part of this library to implement the GetSomething method. Is there a C# construct that allows one to enforce this?
Not looking at design review of this - just want to know if its possible at all without manually enforcing via code reviews.
You can't do that with out-of-the-box C#. C# has abstract classes and interfaces, but they require a specific signature for a method, not just a name.
You could get this working by creating code analyzers in Roslyn, where you check your code if it has the required method.
However, I don't think you should all this. I think you are making a design flaw here in requiring a method with a specific name, without forcing the arguments of it.
You could always implement a method similar to the Main method found in every C# application. It uses a string[] as parameter where you can put a number of variables in. In your case I would opt for an object[]. However, this design has its flaws too obviously.
What is the purpose of a class with method of unknown arguments. It is just illogical in terms of OOP. How are you going to call this method? If arguments are homogeneous then you could just do something like:
public interface IBaseInterface
{
public int GetSomething(Dictionary<string, object> args); // keys matter
}
or
public interface IBaseInterface
{
public int GetSomething(params object[] args); // order matters
}
In some cases Func<> / Action<> high-order functions may be useful.
If you provide a usage case, we would be able to make a more precise answer.
Show how you are going to call such method and I will try to show how to make it better.
Answering your question only from technical side, you could do the following:
public abstract class BaseClass
{
protected BaseClass()
{
if (this.GetType().GetMethod("GetSomething") == null)
throw new InvalidOperationException("BaseClass subclasses should implement 'GetSomething' method");
}
}
public class ClassOne : BaseClass {
public int GetSomething (int a, int b, out int c) { }
}
public class ClassTwo : BaseClass {
public int GetSomething (int a, out string b) {}
}
It will not guarantee this behavior at design-time, but will ensure that such methods exists at run-time.
Add an interface with the method you want.
Set classes inherit from this interace
interface ISampleInterface
{
void SampleMethod();
}
class ImplementationClass1 : ISampleInterface
{
// Explicit interface member implementation:
void ISampleInterface.SampleMethod()
{
// Method implementation.
}
}
How about encapsulating parameters in a "Criteria" object?
public interface IGettable
{
int GetSomething (Criteria crit);
}
public class Criteria
{
public CriteriaType type {get; set;};
public int a {get; set;};
public int b {get; set;};
...
public static Criteria ClassOneCriteria(int a, int b)
{
return new Criteria
{
type = CriteriaType.ClassOneCriteria,
a = a,
b = b
}
}
...
}
public enum CriteriaType
{
ClassOneCriteria,
ClassTwoCriteria
}
public class ClassOne : IGettable
{
public int GetSomething (Criteria crit)
{
if (crit.type != CriteriaType.ClassOneCriteria)
throw new Exception("Invalid criteria type for Class One");
...
}
}

Instantiating a generic field of a class

Is there a way to have a generic field in a class to specialize to a specific type in the constructor?
For example:
class concreteClass1
{
private int a;
public concreteClass1( int a)
{
this.a = a;
}
}
class concreteClass2
{
string b;
public concreteClass2(string b)
{
this.b = b;
}
}
class A<T>
{
private T field;
public A(int x)
{
field = new concreteClass1(x); //error here CS0029
}
public A(string y)
{
field = new concreteClass2(y); //error here CS0029
}
}
So T can be either concreteClass1 or concreteClass1 and their respective ctors will have different signatures.
I would refactor this to use dependency injection. That way the class doesn't contain code to create other classes that it depends on, like myConcreteField = new ConcreteA<T>(4);. Dependency injection is used to keep code from getting tied into difficult knots like this.
(Your example is very, very abstract, which makes it a little difficult. If you use class names like "Concrete" and "Implementation" then it makes the answer harder to read because we use those same words to describe concepts.)
Instead, whatever that Concrete thing is, declare an interface, like
public interface ISomethingThatTheOtherClassNeeds<T>
{
public int MySomething {get;set;}
}
public class SomethingThatTheOtherClassNeeds : ISomethingThatTheOtherClassNeeds<string>
{
public int MySomething {get;set;}
}
Then in your Implementation class:
class Implementation<T>
{
private readonly ISomethingThatTheOtherClassNeeds<T> _something;
public Implementation(ISomethingThatTheOtherClassNeeds<T> something)
{
_something = something;
}
void DoSomething()
{
Console.Write(_something.MySomething.ToString());
}
}
The difference is that instead of being responsible for creating whatever that class is, it's passed to Implementation in the constructor. Implementation doesn't even know what the class is - it just knows that it matches the interface.
This is especially helpful if those other classes in turn depend on more classes. If you're creating them by calling new in your class then that class has to know how to create those classes.
Then to wire it up you would use a dependency injection container like Windsor, Unity, Autofac, and many more. That's not very commonly done with console applications, but I'm guessing this is more experimental than real.
Well this was a bit tricky due to having to convert types. Maybe this will work for you?
class Program
{
static void Main(string[] args)
{
var myImplementation = new Implementation<int>(4);
var myImplementation2 = new Implementation<string>("Hello World");
Console.WriteLine(myImplementation.myConcreteField); // outputs 4!
Console.WriteLine(myImplementation2.myConcreteField); // outputs Hello World
}
}
abstract class MyAbstract<T>
{
public T MySomething;
public MyAbstract(T something)
{
MySomething = something;
}
}
class ConcreteA<T> : MyAbstract<T>
{
public ConcreteA(int something) : base((T)Convert.ChangeType(something, typeof(T)))
{
}
}
class ConcreteB<T> : MyAbstract<T>
{
public ConcreteB(string something) : base((T)Convert.ChangeType(something, typeof(T)))
{
}
}
class Implementation<T>
{
public MyAbstract<T> myConcreteField;
public Implementation(T a)
{
myConcreteField = new ConcreteA<T>(4);
}
void DoSomething()
{
Console.Write(myConcreteField.MySomething.ToString());
}
}

Interface injection

Is it possible to inject an interface into an existing 3rd party class that I can not alter? Like extension methods but for an interface (and its implementation for the class that it had been injected to).
I like to optionally use one of two similar 3rd party libraries by giving classes that are similar in both libraries the same interfaces. So that I do not have to convert there classes into mine.
I don't completely understand what you mean about injecting an interface, but you could use the Adapter pattern to achieve this. See also: http://dofactory.com/Patterns/PatternAdapter.aspx
Create your own interface, then create your own classes that implement the interface, which contain/wrap the 3rd party classes.
As long as you're dealing with interfaces, why not just go with wrapping the classes in your own classes, that implement the interfaces?
You should look at the Decorator Pattern which allows you to extend a class by composition.
e.g.
Given sealed class A which implements InterfaceA:
public interface InterfaceA
{
int A {get; set;}
}
public sealed Class A : InterfaceA
{
public int A {get;set;}
}
You could extend InterfaceA and then use a decorator class B to encapsulate an instance of class A and provide additional methods.
public interface MyExtendedInterfaceA : InterfaceA
{
int B {get;set}
}
public class B : MyExtendedInterfaceA
{
private InterfaceA _implementsA = new A();
public int A
{
get
{
return _implementsA.A;
}
set
{
_implementsA.A = value;
}
}
public int B {get; set;}
}
Alternatively, decorator Class C could add a whole new interface:
public interface InterfaceC
{
int MethodC();
}
public class C : InterfaceA, InterfaceC
{
private InterfaceA _implementsA = new A();
public int A
{
get
{
return _implementsA.A;
}
set
{
_implementsA.A = value;
}
}
public int MethodC()
{
return A * 10;
}
}

Categories

Resources