How to implement chat commands as separate classes? - c#

I am currently working on the chatbot for the Twitch channel and would like to have all the commands to be separate classes in the program so that I will only need to add or remove a single class to add or remove command.
I've searched through the Internet for quite long but never came across the suitable design. Below is what I think it has to look like but can't find the proper syntax.
class Command()
{
string keyword;
int globalCooldown;
List<string> args;
}
class DoStuffA : Command(List<string> _args)
{
keyword = "pleasedostuffa";
globalCooldown = 2;
args = _args;
DoStuff(List<string> args)
{
//doing stuff A here with all the logic and so on
}
}
class DoStuffB : Command(List<string> _args)
{
keyword = "pleasedostuffb";
globalCooldown = 8;
args = _args;
DoStuff(List<string> args)
{
//doing stuff B here with all the logic and so on
}
}
Why do I need this is because I want to store all possible commands in the List<Commands> and when the new chat message appears, search which object of this list matches the keyword with the chat command and execute the appropriate function. For example, if someone posts !pleasedostuffa, I perform
foreach (Command c in commands)//commands is List<Command>
{
if(c.keyword==receivedCommand.command)//.command is string
{
c.DoStuff(receivedCommand.argsAsList)//.argsAsList is List<string>
}
}
I hope I explained this properly and really am eager to have at least a clue on how could this implemented.
Thank you in advance!

You have the method setup almost right, though there are a few other changes you need. You need to have the base class expose DoStuff() as a virtual method. Try this:
public abstract class Command
{
public string keyword;
public int globalCooldown;
//List<string> args;
public abstract void DoStuff(List<string> args);
}
public class DoStuffA : Command
{
//public string keyword = "pleasedostuffa";
//public int globalCooldown = 2;
//args = _args;
public DoStuffA()
{
keyword = "pleasedostuffa";
globalCooldown = 2;
}
public override void DoStuff(List<string> args)
{
//doing stuff A here with all the logic and so on
}
}
public class DoStuffB : Command
{
//public string keyword = "pleasedostuffb";
//public int globalCooldown = 8;
// args = _args;
public DoStuffB()
{
keyword = "pleasedostuffb";
globalCooldown = 8;
}
public override void DoStuff(List<string> args)
{
//doing stuff B here with all the logic and so on
}
}
So, a couple of notes.
Method inheritance
Here I make the base class abstract, simply to enforce that each and every child command implements the abstract function DoStuff(). After all, what would you do with an instance of the base class? It wouldn't do anything, because you don't have an actual implementation. So abstract helps both to avoid accidentally instantiating Command itself and also makes sure sub-type implementers do the right thing.
Second, at the child class level, you need to override the method on the base class. This ensures that anything calling ((Command)doStuffB).DoStuff() gets the proper implementation of the function.
Now that you have a DoStuff() method on Command, your foreach loop should work as you expect. You have the method available on the base class, so the virtual overrides at the child level can be run without casting.
Base class member access
The fields you are trying to declare here, keyword and globalCooldown, aren't how people would typically expose information like this, but before we get to that I'm going to explain the more fundamental principle of accessing base-class members from the inherited classes.
These two fields need to be marked public (and given a proper type) so that they can be used from outside the class (in your foreach). The public keyword is called an accessibility modifier, and there are a few other options for accessibility, but in your case only public is likely to do what you want.
As you can see, I've commented out the fields in the child classes. If you declare them there, they will hide (but not override) the members of the same name on the base class. There's no equivalent of virtual or abstract for fields, so you need another strategy. Here, we leave your original declaration of those fields on the base class so that they are available to anything holding any type of a Command. But instead of redeclaring them at the child class level, we simply set the values of the base class members in the constructor for the child classes.
Note that for clarity's sake, you could explicitly specify that you are setting a member on the base class by using base.keyword = "etc"; instead.
Exposing internal values via properties
As I noted, this will work, but it's not quite how most people would expose the keyword and globalCooldown values. For this, you'd typically use a property instead. This lets you store and expose the values without risking letting someone change the value (intentionally or unintentionally). In this case, you'd want to declare the property this way:
public string Keyword // properties start with a capital letter by convention
{
get; // The get accessor is public, same as the overall property
protected set; // the set accessor is protected
}
The protected set accessor means that this is still accessible to be set by the child classes, but not by anyone else. This is probably what you want. So now, in your child constructor, you can set base.Keyword = "whatever"; and your foreach code can reference, but not overwrite, that value. You can declare GlobalCooldown in a similar way.

Related

Derived constructor with type parameter

EDIT: added follow up question from getting a solution suggested from another question
EDIT2: I just realised that my follow up question was not needed.
Is it possible to have an abstract base class with a type parameter of T have a constructor that takes a parameter of T and assigns it to a property of T? What i want to achieve is that all derived classes has a constructor that does this?
Something like:
public abstract class NotificationBase <T>
{
public string Text { get; set; }
public T Context { get; set; }
public NotificationBase(T context, string text)
{
Context = context;
Text = text;
}
}
public class NumberNotification : NotificationBase<int>{}
public class Program
{
public void Run()
{
var thing = new NumberNotification(10, "Hello!");
}
}
EDIT:
I got a link to another question that explained how to do this which is great. However i have some issues with that. And i dont mean its wrong, if that is the only way to do it then thats how it is. However its not the ideal situation for what im trying to do. I explain. This was the solution:
public class Base
{
public Base(Parameter p)
{
Init(p)
}
void Init(Parameter p)
{
// common initialisation code
}
}
public class Derived : Base
{
public Derived(Parameter p) : base(p)
{
}
}
..which works great. However it does create two small issues that id like to se if they can be addressed.
What i want is to force all classes that derives from the base to pass a T into the constructor so that its mandatory. With this solution, its possible to leave it out.
If all classes should do this then it feels redundant to create a constructor to propagate a mandatory parameter.
EDIT: I just realised that demanding a constructor that propagates the type parameter IS what im looking for. I makes sure that the T property gets a value and also allows for other things to happen in the constructor.
Yes, you can, you just need to propagate the constructor chain using the relevant type, and call the ancestor if needed:
public class NumberNotification : NotificationBase<int>
{
public NumberNotification(int context, string text)
: base(context, text)
{
}
}
Without constructor in child class, the instantiation you wrote can't compile because you don't offer a way for the compiler to know what to do.
You can also offer any other constructor needed.
Therefore now this compiles and works:
var thing = new NumberNotification(10, "Hello!");
Inheritance And Constructors (C# Corner)
base (C# Reference)
Define the parameterized constructor for NumberNotification class which should invoke the required constructor of NotificationBase using base
public class NumberNotification : NotificationBase<int>
{
public NumberNotification(int context, string text)
:base(context, text)
{
}
}
Now for NumberNotification object, context is type of int as here T is marked as int type which Yyou can check using below code:
var thing = new NumberNotification(10, "Hello!");
Console.WriteLine(thing.Context.GetType());
The above prints the output as System.Int32
Check the fiddle - https://dotnetfiddle.net/keufQO

How to deal with temporal coupling?

I'm struggling because of this:
My classes have some methods that have temporal coupling. This is, some method MethodA has to be invoked first to "initialize" the data that MethodB needs to work properly.
I usually make the temporal coupling explicit by passing the offending dependency to "MethodB" as argument, like in this snippet:
private class SomeClass
{
private string field;
private int count;
public SomeClass()
{
MethodA();
MethodB(field);
}
private void MethodA()
{
field = "Something";
}
private void MethodB(string str)
{
count = str.Length;
}
}
Although it makes things explicit I feel I'm doing something wrong. I end up having method that don't use fields at all (static methods!), so the class starts to seem less cohesive.
Is this the best way to do it? (losing cohesion by passing arguments)
EDIT: Regarding some answers that suggest using field as a parameter in the constructor or using the Builder Pattern to avoid invalid states: I cannot do that, because in my case I'm building a Parser. MethodA reads the input and sets the state depending on it (reading characters from a file) and then, MethodB is invoked. They have to be invoked in the correct order. That is the real problem: one should be invoked before the other.
If you follow Anemic Domain Model, you can break your class and make it 2 smaller classes. You become aware of bad design because your current class violates SRP, in short it has 2 responsibility: 1 for handle the input process, 1 for process the input result.
Break it down so that ClassA will handle the input and returning result, then ClassB will take the result from ClassA as parameter, then process it. ex:
public class ClassA
{
public string MethodA()
{
// read the input
return "Something"; // or return the input
}
}
public class ClassB
{
private int count;
public void MethodB(string str)
{
count = str.Length;
}
}
If you find the use of both class is bothersome, use another aggregate service for that. ex:
public class ClassC
{
public ClassA ClassA = new ClassA();
public ClassB ClassB = new ClassB();
public void Execute(){
string result = ClassA.MethodA();
ClassB.MethodB(result);
}
}
Fluent API's solve this kind of thing on public interfaces by not exposing dependent methods in the "builder" object until appropriate:
SomeClass someInstance = SomeClassBuilder(x=> {
x.MethodA().MethodB("somevalue");
});
This requires alot more plumbling because you need the builder object, as well as builder components such as an object that is returned from MethodA which exposes MethodB. This way the only way to call MethodB is to first call MethodA.
I'm not encouraging you to take this approach. It's probably overkill for many scenarios, but is important to be aware of this option in case you encounter a scenario where it is appropriate.
I guess you need to have a sort of complex initialization, in which some parameters have to be specified before actually initialize the object, and you want a better control on what the class user is doing to avoid invalid states. A good know pattern to solve such situation is the so called "Builder Pattern", very frequently used in OOP. I don't want to point a particular article, you will find yourself a lot of examples by just using the keyword "builder pattern". Just to be complete, the overall idea is to make a fluent sequence of method specifying values of internal fields, and delegate a final method "Build" to create an working object instance, and validate the parameters passed.
I don't know what is your exact goal, but why not put the parameter in the constructor of the class:
private class SomeClass
{
private string _field;
private int _count;
public SomeClass(string field)
{
_field = field;
_count = field.Length;
}
}
Now you will have something like this
SomeClass sc = new SomeClass("Something");//or whatever you want for field.
You can just remove the parameter from MethodB and use the field, in this way you don't lose cohesion
private class SomeClass
{
private string field;
private int count;
public SomeClass()
{
MethodA();
MethodB();
}
private void MethodA()
{
field = "Something";
}
private void MethodB()
{
count = field.Length;
}
}
Notes:
1) The way you describe the problem seems like Template Method design pattern, you should have a look here.
2) Static methods don't belong to that class

Base class object as argument for derived class

(Simplified) Scenario:
public class BaseClass
{
public int BaseClassInt {get; set;}
public BaseClass(int pBaseClassInt)
{ this.BaseClassInt = pBaseClassInt; }
}
public class DerivedClass : BaseClass
{
public int DerivedClassInt {get; set;}
public DerivedClass (int pBaseClassInt, int pDerivedClassInt) : base(pBaseClassInt)
{ this.DerivedClassInt = pDerivedClassInt; }
}
If I want to instantiate a DerivedClass-object I have to pass all arguments required to create a BaseClass-object and a DerivedClass-object. Also for every BaseClass-constructor I have to (at least should in my concrete case) provide a constructor with the same arguments in the derived class, plus arguments for the derived class properties. Then, if I change or delete a constructor in the base class I have to change or delete the corresponding contructor in the derived class(es).
I wonder if it is possible to use a constructor for the derived class which accepts a base class-object as an argument:
public DerivedClass(BaseClass pBaseClassObejct, int pDerivedClassInt)
{
// to make clear what I intend to do - looks silly of course
this = (DerivedClass)pBaseClassObject;
this.DerivedClassInt = pDerivedClassInt;
}
This could be called:
DerivedClass DerivedClassObject = new DerivedClass((new BaseClass(1),2);
If constructors in the base class would change, I wouldn´t have to mind it for the derived class. Is there any way to achieve this?
Think about this line for a moment:
this = (DerivedClass) pBaseClassObject;
Let's ignore the fact that you cant set this directly that way, and focus on the rest.
Imagine Giraffe and Elephant are both implementations of AfricanAnimal:
// By extension, ellie is also an AfricanAnimal
Elephant ellie = new Elephant();
// assume ellie is passed in as a param here (she can
// be, because she is an AfricanAnimal after all!):
public Giraffe(AfricanAnimal ellie)
{
this = (Giraffe) ellie; // Can't do this!
}
You can't (and would not want to) force ellie into being a giraffe, because a giraffe may have properties etc. that ellie lacks, and ellie may have properties that Giraffes don't have. Yet, using an AfricanAnimal as your parameter type there, would allow for just that.
Note: You could write that code and pass a Giraffe in, and all would be fine, but then again, that makes little sense; then you might as well use the Giraffe type as the parameter.
If you replace this with an instance variable, you would be able to compile with something like the following...
public Giraffe(AfricanAnimal ellie)
{
this.varOfTypeGiraffe = (Giraffe) ellie;
}
... but as soon as you run it with an Elephant as a a prameter, you will get an exception similar to:
InvalidCastException: Unable to cast object of type 'Elephant' to type 'Giraffe'.
TL;DR: This is a bad idea. Don't even try.
You cannot make a base constructor run from inside the body of any derived method (including the derived constructor). Even if you could, a base instance would not have retained any information about which constructor was used to instantiate it so there would be no way to know which base constructor should be called.
The above refers to the general case where a base constructor can potentially modify application state not directly related to the base class (e.g. by changing the value of static fields somewhere). You could use reflection to copy property values from a base instance to the derived instance being created, but this is practically unworkable because
It requires that you create a base instance in the first place -- what if the base is abstract, or if creating one has side effects?
You need a guarantee that the base constructor does not modify application state. But the aim here is to be independent of what the base constructors do, so you are back to square one.
No, that is not possible and should not be, because it doesn't make sense.
If it was possible and you deleted/changed the base class constructor, you would still need to change the code which creates the base class object that you would use as an argument to the derived class constructor.
Also, not all base classes are concrete. You would not be able to create an abstract base class, right?
This feature is not available. I think what you want is a little like this:
Suppose C# had a keyword allbaseargs and allowed code like this:
public class DerivedClass : BaseClass
{
public int DerivedClassInt { get; set; }
public DerivedClass (allbaseargs, int pDerivedClassInt)
: base(allbaseargs)
{
DerivedClassInt = pDerivedClassInt;
}
}
Then this could only work if BaseClass had only one (accessible) instance constructor.
The compiler should then examine the sole base constructor and substitute the magical word allbaseargs with the parameters of that constructor.
However, C# does not have this feature, and you would have to hand-code everything, which includes changeing all : base(...) calls of all derived classes when the constructor signature changes.
It is allowed to have the signature:
public DerivedClass(BaseClass pBaseClassObejct, int DerivedClassInt)
like you suggest, but you would not be able to chain the : base(...) easily. You would have to equip BaseClass with a construtor that took another instance in and copied all "state" (all instance properties and fields and such) from that other instance to "this". I do not recommend that solution.
This might be help!
Solution A: Create Inherit instead of base!
public static class Test
{
public static T Foo<T>(string text, int num) where T : BaseClass
{
T #base = (T)Activator.CreateInstance(typeof(T), new object[] { text, num });
//...
return #base;
}
public static void Main()
{
InheritClass inherit = Foo<InheritClass>("Hi there", 10);
}
}
Solution B: Copy base to inherit
public static class Test
{
public static TInherit As<TBase, TInherit>(this TBase #this) where TInherit : TBase
{
var type = typeof(TInherit);
var instance = Activator.CreateInstance(type);
foreach (var property in type.GetProperties())
if (property.CanWrite)
property.SetValue(instance, property.GetValue(#this, null), null);
return (TInherit)instance;
}
public static BaseClass Foo(string text, int num)
{
BaseClass #base = new BaseClass(text, num);
//...
return #base;
}
public static void Main()
{
InheritClass inherit = Foo("Hi there", 10).As<BaseClass, InheritClass>();
}
}
Notes: you can have simple 'As()' found here, but i prefer mine (where Inherit : TBase), where it's more safe and support converting base to inherit of inherit class.

How to tell if MemberInfo represents an override

Given the following code:
public class Base {
public virtual void Method() { }
}
public class Derived : Base {
public override void Method() { }
}
...
var baseMethodInfo = typeof(Base).GetMember("Method")[0];
var derivedMethodInfo = typeof(Derived).GetMember("Method")[0];
Is it possible to determine if the derivedMethodInfo represents a method declaration which overrides another in a base class?
In another question it was observed that had Method been declared abstract (and not implemented) in the base class, derivedMethodInfo.DeclaringType would have turned up as Base, which makes sense after reading #EricLippert's comments. I noticed that in the present example, since the derived class re-declares the method, that derivedMethodInfo.DeclaringType == derivedMethodInfo.ReflectedType, viz. Derived.
There doesn't seem to be any connection between baseMethodInfo and derivedMethodInfo, other than their names are the same and their respective declaring types appear in the same inheritance chain. Is there any better way to make the connection?
The reason I ask is that there appears to be no way to distinguish, through reflection, between the earlier example and the following one:
public class Base {
public virtual void Method() { }
}
public class Derived : Base {
public new void Method() { }
}
In this case as well, the Derived class both declares and reflects a member called Method.
A method shadowing a virtual method will have the VtableLayoutMask flag set in Attributes.
Note that an ordinary virtual method (with no similar name from a base type) will also have this flag set.
This flag appears to indicate that the method introduces a new entry in the VTable.
There's a more specific class MethodInfo which derives from MemberInfo. Note that not all kinds of members can be virtual (fields cannot, for example).
If you say
var derivedMethodInfo = typeof(Derived).GetMethod("Method");
then you can check if
derivedMethodInfo.GetBaseDefinition() == derivedMethodInfo
or not. See documentation for GetBaseDefinition() where they also have a code example.

How can I ensure that a class has just 1 constructor in .NET?

Well my question is pretty self-explanatory. I have a class and I want to ensure that there is just 1 public constructor to this class. Moreover, I also want to ensure that the constuctor should have just 1 parameter. My class will be modified by many different developers, and I am looking for a way to ensure that they do not write any more constructors than are currently specified. Is it possible? If yes, then how?
Note, my class inherits from another class which currently does not have any constructor but it might have in the future. I don't know if this information will affect the answer or not but just thought of adding it.
Please help!
Thanks in advance!
You could consider writing a unit test to encode this design constraint. As long as the test isn't fiddled with, this will warn when the contraint is broken.
This would be a good case for a nice comment in your class detailing this constraint.
The following testing approach can be expanded to provide a test which could test derived types, rather than a single type. This approach is a type of static analysis, and removes the overhead that would be incurred by expensive runtime checking through reflection for instance. A test ensures that the design constraint is validated at build time, rather than at runtime which could be after code is released.
[Test]
public void myClass_must_have_one_single_paramter_ctor()
{
Type type = typeof(MyClass);
const BindingFlags Flags = (BindingFlags.Public | BindingFlags.Instance);
ConstructorInfo[] ctors = type.GetConstructors(Flags);
Assert.AreEqual(1, ctors.Length, "Ctor count.");
ParameterInfo[] args = ctors[0].GetParameters();
Assert.AreEqual(1, args.Length, "Ctor parameter count.");
Assert.AreEqual(typeof(string), args[0].ParameterType, "Ctor parameter type.");
}
public class MyClass
{
public MyClass(string woo) {}
}
All classes have one constructor. If you don't specify one in the source code, the compiler will add an empty public constructor - the equivalent of:
public class MyClass
{
public MyClass()
{
}
}
However if you specify at least one constructor in the source, only the constructors that you explicitly specify will be created, e.g. the following class has one public constructor that takes a single string parameter:
public class MyClass
{
public MyClass(string myParameter)
{
...
}
}
In short, there's nothing special you need to do. If you only want one public constructor then ... just write one public constructor.
Only the person who codes the class can restrict the number and type of constructors.
So if that is you, then you can just code it the way you want.
This could be achieved using reflection. The only thing you need to take care is, the base class code shouldn't be accessible to or editable by developers.
class Program
{
static void Main(string[] args)
{
Inherited obj = new Inherited("Alpha");
obj.test();
Inherited1 obj1 = new Inherited1(); //This will fail as there is no ctor with single param.
obj1.test();
}
}
public class MyBase
{
private static IList<string> ValidatedClasses = new List<string>();
public MyBase()
{
if(!ValidatedClasses.Contains(this.GetType().FullName) &&
!ValidateConstructorLogic())
{
throw new ApplicationException("Expected consturctor with single argument");
}
}
public bool ValidateConstructorLogic()
{
bool ValidConstFound = false;
foreach (var info in this.GetType().GetConstructors())
{
if(info.GetParameters().Length ==1)
{
lock (ValidatedClasses)
{
ValidatedClasses.Add(this.GetType().FullName);
}
ValidConstFound = true;
}
}
return ValidConstFound;
}
}
public class Inherited:MyBase
{
public Inherited(string test)
{
Console.WriteLine("Ctor");
}
public void test()
{
Console.WriteLine("TEST called");
}
}
public class Inherited1 : MyBase
{
public void test()
{
Console.WriteLine("TEST called");
}
}
You could use FxCop to validate your code against a set of predefined rules. I beleive this might be the apt solution to your problem. If you need help on creating custom FxCop rules, please refer this article.
Constructors are not inherited from base classes.
Your class will have only the constructors that you write, except for (as others have pointed out) a default public constructor that is generated by the compiler when you do not explicitly provide one of your own.
You could try using a nested builder, as described by Jon Skeet. Basically: You force the user to go through the builder which then calls the private class constructor. Since the class constructor is private, only the nested builder has access to it.
Alternative: Use static factory methods, make the constructor private & document your intentions.
Based on your comments, I don't think this is a "coding" problem. This is a policy & enforcement problem. You don't want other developers in your team creating more constructors.
In that case, go tell them that. Whoever is in charge of your source code repository can enforce it by rejecting changes that break the policy. Adding code to deal with this is just going to add runtime penalties to users for no reason.

Categories

Resources