-
Notifications
You must be signed in to change notification settings - Fork 0
Interfaces
This covers some of the most important basics of this library!
Let's go over the more simple first.
All command modules will implement this interface, it is impossible to Register a command without this ValueTask OnCommandExecute(MethodInfo, object, object[], object?)
and the property Handler UserHandler
.
- MethodInfo method - The method being invoked
- object instance - The instance of the type to which the
method
belongs to - object[] invokes - The object instances that were used to invoke the
method
- object? returnInstance - The returned type instance of the
method
if any
This interface is only used by the Handler to log messages like debug, info, warnings, and errors.
We must implement these 5
methods from this interface.
void Log(string, LogLevel)
void LogDebug(string)
void LogInfo(string)
void LogWarning(string)
void LogError(string)
These are pretty self explanatory with their arguments, so no need to include the params.
This interface is used to convert objects that cannot be parsed by the IStringHandler
via the primal conversion methods.
Instead it provides the flexibility for you to build upon your own IStringHandler
and create types that can be converted by string.
class Person() { public string name; }
class PersonConverter : IConverter<Person>
{
public ValueTask<Person> Convert(object[] previousArgs, string parse, object[] afterArgs)
{
//Understanding:
//parse = The exact argument that needs to be converted. This is raw string passed in by a user! This can be one word longer
//previousArgs/afterArgs = objects passed in by YOU, these can help you create command modules that require a certain object set before or after
var person = new Person();
person.name = parse; //we don't really care about the information that is passed and just want to set the name so it is not null
return parse;
}
}
The most complicated interface to implement as it pushes you to create your own StringConverter
just like this one here
Converters is one of the most important part for the IStringConverter
because the user is doing work for you!
void RegisterConverter<T>(Func<object[], string, object[], ValueTask<T>);
This method provides the possibility to create a primitive converter without making a IConverter<T>
. This can sometimes be the better solution when making a simple converter, like the example above.
We should take note that the Type we register with SHOULD be SAVED, so it can be used for UnRegisterConverter or UnRegisterConverter(Type)
Since the library uses ValueTask we can use async delegates!
stringConverter.RegisterConverter<Person>(async delegate(object[] prev, string parse, object[] after)
{
return new Person()
{
name = parse
};
});
Simply takes in a IConverter instance. You can do whatever you like with this
void RegisterConverter<T>(IConverter<T>);
Sort through the types we've registered and remove it!
UnRegisterConverter(Type)
UnRegisterConverter<T>()
Now that we've registered our converter, we should let the user know if their converter has been registered 😕
bool CanConvert(Type)
bool CanConvert<T>()
Simply use those registered types
that you should have saved and check for them in your cache, dictionary, list, or whatever you are using!
Now that the user can register
, unregister
, and see if the can
convert we can now use the converter!
bool UseConverter(Type, object[], string, object[], out ValueTask<object>)
bool UseConverter<T>(object[], string, object[], out ValueTask<T>)
You should return if the converter was successful.
I also recommend using
CanConvert(Type)
in these methods
So, what should go inside the UseConverter
method?
Simply put, check if the Converter type is registered, find the converter, and use the ValueTask<T> Convert(object[], string, object[]
method or the delegate from other RegisterConverter
method.
Ok, everything so far should have been pretty simple to figure out. Adding converters to your cache, dictionary, or whatever it is definitely not the most extreme task 🧇
So, now let's work on creating the most important part of this entire interface which is CastString
the method that should be able to handle a few primitive types.
The basic
StringConverter
can convertEmpty ctor classes
,Classes with a single string ctor
,Digits
, andEnums
.
Important: GlobalCastString
The method above should be the user's last resort since instead we want to use the Converters we registered earlier.
bool CastString(object[], string, object[], Type, out ValueTask<object>, out string)
bool CastString<T>(object[], string, object[], out ValueTask<T>, out string)
So, your CastString
method should look something like this:
public bool CastString(object[] before, string from, object[] after, Type castType, out ValueTask<object> converted, out string error)
{
if(UseConverter(castType, before, from, after, out converted)) //use a converter if we can
{
error = string.Empty;
return true;
}
//we should have some kind of static method to use here. This allows the user to cast a string to primitive types
return GlobalCastString(from, castType, out converted, out error);
}
public bool CastString<T>(object[] before, string from, object[] after, out ValueTask<T> converted, out string error)
{
bool ret = CastString(before, parse, after, typeof(T), out ValueTask<object> conversion, out error);
//change the result from object to type T
converted = ValueTask.FromResult((T)conversion.Result);
return ret;
}