The project I am working on requires some executions to be done at a certain time. I am not sure what would be the best way to deal with this situation. The method must be able to survive server restart/maintenance. And method calls must be programmatically.
I am considering going down this path:
I could have a table in database (or even a message queue) called TaskTable which could have TaskID(PK), TaskName(varchar), TaskStatus(enum success,failed, scheduled) and TimeOfExecution. But I need a windows service that periodically polls the database for any unexecuted tasks. Problem I am facing is that: What do I use as the TaskName to save into database? Class name? class and method name ToString? And how can I convert the string back and programmatically invoke the method calls (I don’t want to have a giant switch statement)? A typtical task would look like below. So I ned to be able to get the name of the task "SendIncompleteNotification" and class name save it into database and on retrival invoke programatically
public static Task<string> SendIncompleteNotification
{
get
{
return new Task<string>
(
a => Console.WriteLine("Sample Task")
, "This is a sample task which does nothing."
);
}
}
The problem now is I am having problem saving the method/property name progrmatically.
var type = ApplicationTask.SendIncompleteNotification.GetType();
//type.Name shows "Task`1" rather than SendIncompleteNotification
Is there any better ways of dealing with this situation? Thanks!
Updated:
Sorry my head was spinning. I now realized what I did wrong was to have another method/property to return my Task. What I should have done was to have a new class inhrite from my Task. And there i can easily get the class name and save the string into db and later retireve back and invoke.
Is the database a requirement?
If not, what about a Windows Scheduled Task (they have a tendancy to "just work") which calls into a general console app. The arguments to the console app could be:
A DLL containing the task to execute
The name of a class implementing an interface you define
Other arguments
This way you can put all of your tasks into one assembly, or multiple. Alternatively you could create an attribute, apply that attribute to your tasks to give them a "friendly name", and use reflection over the assembly to find classes with the matching attribute.
Edit: example:
interface ITask
{
void Execute(ExcecutionContext context);
}
[TaskName("Send Emails")
class SendEmailsTask : ITask
{
public void Execute(ExcecutionContext context)
{
// Send emails. ExecutionContext might contain a dictionary of
// key/value pairs for additional arguments needed for your task.
}
}
class TaskExecuter
{
public void ExecuteTask(string name)
{
// "name" comes from the database entry
var types = Assembly.GetExecutingAssembly().GetTypes();
foreach (var type in types)
{
// Check type.GetCustomAttributes for the TaskAttribute, then check the name
}
}
}
Edit 2: This is in answer to your code sample.
class YourClass
{
public static Task<string> SendIncompleteNotification
{
get {
return new Task<string>(
s => Console.WriteLine("Executing task... arguments: {0}", s),
"My task");
}
}
}
interface ITask
{
void Execute(object o);
}
class Task<T> : ITask
{
public Task(Action<T> action, string name)
{
Action = action;
}
public string Name { get; set; }
public Action<T> Action { get; set; }
void ITask.Execute(object o)
{
Action((T)o);
}
}
class Program
{
static void Main(string[] args)
{
// Assume that this is what is stored in the database
var typeName = typeof (YourClass).FullName;
var propertyName = "SendIncompleteNotification";
var arguments = "some arguments";
// Execute the task
var type = Type.GetType(typeName);
var property = type.GetProperty(propertyName);
var task = (ITask)property.GetValue(null, null);
task.Execute(arguments);
Console.ReadKey();
}
}
You might want to look into Windows Workflow. They are designed for long running processes, can be persisted to a database and woken up on event or timer, as far as I know.
Store the assembly FullName, and type FullName and the method name. Assuming the method signature is something predictable (like no parameters and returning void)
1) create an instance of the assembly using the static LoadFrom method of the Assembly type.
2) get a reference to the class type from your assembly using the GetType method
3) get MethodInfo instance from the type using the GetMethod method
4) create an instance of the type using Activator.CreateInstance
5) execute the method using the Invoke of the MethodInfo instance, passing in the class instance from step 4. (sorry that I'm at a public computer without a copy of VS to crank out real code but those 5 steps would do.
Also if you're using SQL 2005 consider using a SqlDependency object and getting "notified" when your talbe changes rather than polling.
Have you looked at Quartz, it works pretty well, and I'm pretty sure it implements all the features you need.
Related
Good day, everyone,
recently I've come across the Discord.NET Api and was in love with the way Commands were handled. Essentially, to add a new Command that is executed when you write !ping, you can do this:
[Command("ping")]
public async Task Ping()
{
//some logic here
}
And I really liked the easy nature of integrating new commands in an already existing API. So I wanted to recreate what was going on. In the beginning I was absolutely confused by the introduction of metaprogramming, but now feel a little more comfortable, so I tried to start, and designed an Attribute that was only assignable to methods:
[AttributeUsage(AttributeTargets.Method)]
public class Command : Attribute
{
public string Name { get; set; }
public Command(string name)
{
Name = name;
}
public Command()
{
Name = string.Empty;
}
}
Basic idea then is, that when my Console gets a command, I can run a method that has the command attribute and the name of what was entered in the console. So when I enter "ping" in the console, the below method is going to be executed.
[Command("ping")]
public void Ping()
{
//do sth
}
Now to the complicated part. How do I find and especially run that method? That's where I'm stuck right now. I really don't find anything helpful about that question on the .Net documentary or here on stackoverflow. Here is my attempt anyway:
public void Handle(string command)
{
var methods = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetCustomAttributes<Command>().Count() > 0
select t;
//run method where command.name = ping
}
The idea behind that being, to iterate through all available methods in the assembly, and then putting those into a List of some kind and then executing the method that has the command.name of what was passed in as an argument to the Handle function. When I get that to work, I of course will initilaize the methods list in the constructor of that class and not everytime call it when Handle is called, but for simplicity in my question I formulated my question independent of that, to have my example minimal. The question now is, how do I iterate through all methods in my assembly, and save those with the command attribute into a collection, and how do I run a method that has a certain value for the command.Name property?
I'am kind of new to that whole reflection stuff, so if I did something else stupid or you have general tips on that topic please let me know!!
Thanks in advance!!
I have written a small demo application that should help you to complete your logic. Overall, of course, it still has room for improvement, but it works:
using System;
using System.Linq;
using System.Reflection;
namespace DemoApp
{
class Program
{
static void Main(string[] args)
{
string command = Console.ReadLine().Trim();
LogicProvider provider = new LogicProvider();
MethodInfo method = provider.GetType().GetMethods().FirstOrDefault((item) => item.GetCustomAttribute<CommandAttribute>().Identifier == command);
method?.Invoke(provider, null);
}
}
public class LogicProvider
{
[Command("DemoCommand")]
public void MyMethod()
{
Console.WriteLine("Here");
}
}
public class CommandAttribute : Attribute
{
public CommandAttribute(string identifier)
{
this.Identifier = identifier;
}
public string Identifier { get; } = null;
}
}
If DemoCommand is entered in the console, then a search is made in the LogicProvider for a matching method. If there is a match, it is executed.
The whole thing also works with methods that have parameters. In the case of method?.Invoke(), this can then be specified.
I have a service, which calls an Invoke method on different classes, based on a class attribute found via reflection. I am wanting to test that the correct class is instantiated and the method called.
Service:
private void InvokeCorrectClass(string message)
{
//find type from cache of types based on info in message
//_cacheTypes is Dictionary<Type, string>
var type = _cacheTypes.First(p=>p.Value == msg.MessageType).Key;
var instance = Activator.CreateInstance(type);
var invokeMethod = type.GetMethod("Invoke");
invokeMethod.Invoke(instance, new object[] {msg, messageId});
}
Of course, I'm leaving out some null checking and error handling....
Class 1:
public async Task Invoke(object message, int messageId)
{
//process MessageType 1
}
Class 2:
public async Task Invoke(object message, int messageId)
{
//process MessageType 2
}
I know the code is working correctly, as I hit the correct code using breakpoints, but I'm trying to use Moq and XUnit to automate that the correct class is created and called, and am having no luck at all.
Also, neither Class 1 or Class 2 have parameter-less constructors, and a lot of dependencies. I've tried adding a parameter-less constructor so I can Mock it out with the setup:
_testModule.MessageProcessorMock.Setup(i => i.Invoke(It.IsAny<object>, It.IsAny<int>()))
.Returns<object, int>((msg, messageId) =>
{
msgId = messageId;
msgPassedOn = msg;
return Task.CompletedTask;
});
but it is never called.
Here is my structure :
Abstract Class - Action
--Abstract Class - ConfigsAction
---- ResetAction
---- SetToZeroAction
--Abstract Class - SettingsAction
---- EditLanguageAction
---- ChangeColorPrefAction
ManagerAccessPoint.Receive(Action action)
ManagerAccesPoint receives the action and ''sends'' it to the proper ConcreteManager.
So ManagerAccessPoint needs to Cast it either to ConfigsAction or SettingsAction
And ConfigManager/SettingsManager would then cast it to the proper action class would it be ResetAction, SetToZeroAction, EditLanguageAction or ChangeColorPrefAction.
I know i can save the action type with
Object.getType().name
as a string.
I know I can get the type back from the string with
Type.GetType(string)
But how do I cast it back to that type ? It could be visualized as if it was this :
Retrievetype derievedAction = (RetrieveType)myAction
Where retrieveType is a Type variable
I found other ''similar'' question but none were giving me a working solution for my situation.
I actually need to be able to call Child's classe specific function once I received teh action at the right level, so that the behaviour is different for every child class.
What you're asking doesn't make sense. A cast is useful only if the type you're casting to is known statically at compile time, otherwise how would you do anything with it?
In short, you can't. You could use the 'dynamic' object which would allow you write code as if it had been cast, but I don't think that would be appropriate here.
Instead, you could try something like:
class ManagerAccessPoint
{
private ConfigManager _configManager;
private SettingsManager _settingsManager;
void Receive(Action action)
{
var configs = action as ConfigsAction;
if (configs != null)
{
_configManager.Receive(configs);
return;
}
var settings = action as SettingsAction;
if (settings != null)
{
_settingsManager.Receive(settings);
return;
}
}
}
class ConfigManager
{
void Receive(ConfigsAction action)
{
// repeat the same pattern here
var setToZero = action as SetToZeroAction;
if (setToZero != null)
{
// we have a setToZero action!
}
etc...
}
}
The class structure looks fine , and the concept of manager is also fine . But if you need to call a specific functionality of child class then we are losing/going away from the Abstraction concept.
Try to handle these via virtual/abstract contract methods.
For eg:
class ManagerAccessPoint
{
public void Receive (Action action)
{
//where CallContractMethod is an abstract/virtual method
//which serves as a contract and now via run time polymorphism
//the appropriate action method will be called.
//Each and every child class will have different behavior of this action.
action.CallContractMethod();
}
}
Is it possible to get the name of another method in the same class but without using a manually written string?
class MyClass {
private void doThis()
{
// Wanted something like this
print(otherMethod.name.ToString());
}
private void otherMethod()
{
}
}
You may ask why: well the reason is that I must invoke the method later on like this Invoke("otherMethod"), however I don't want to hardcode this string myself as I can't refactor it anymore within the project.
One approach is you can wrap it into delegate Action, then you can access the name of method:
string name = new Action(otherMethod).Method.Name;
You can use reflection (example - http://www.csharp-examples.net/get-method-names/) to get the method names. You can then look for the method that you're looking for by name, parameters or even use an attribute to tag it.
But the real question is - are you sure this is what you need? This looks as if you don't really need reflection, but need to think over your design. If you already know what method you're going to invoke, why do you need the name? How about a using a delegate? Or exposing the method via an interface and storing a reference to some class implementing it?
Try this:
MethodInfo method = this.GetType().GetMethod("otherMethod");
object result = method.Invoke(this, new object[] { });
Btw. I also found (in the expansions of the internet) an alternative solution for only getting the string of a method. It also works with parameters and return types:
System.Func<float, string> sysFunc = this.MyFunction;
string s = sysFunc.Method.Name; // prints "MyFunction"
public string MyFunction(float number)
{
return "hello world";
}
This question already has answers here:
Calling a function from a string in C#
(5 answers)
Closed 1 year ago.
I have a struct-array that contains details of different reports that can be run. Each report calls a different method and currently the program has to manually check the selected report value to specifically call the appropriate method.
I would like to store the method name in the struct-array and then have program invoke that method when there is match. Is this possible?
Currently:
if (this.cboSelectReport.Text == "Daily_Unload")
{
reportDailyUnload();
}
Ideally:
if(this.cboSelectReport.Text == MyArray[i].Name)
{
something(MyArray[i].MethodName);
}
UPDATE
I tired a number of the suggestions below and none of them worked. They didn't work probably due to how I have my program structured.
You can do it using reflection, but IMO it is too fragile: it introduces an invisible dependency on the name of the method that you call.
// Assuming that the method is static, you can access it like this:
var namedReportMethod = "MyReport1";
var reportMethod = typeof(ReporterClass).GetMethod(namedReportMethod);
var res = reportMethod.Invoke(null, new object[] {reportArg1, reportArg2});
A better approach would be to define a delegate based on your method, and store it in the struct/class instead of the method name.
delegate void ReportDelegate(int param1, string param2);
class Runner {
public static void RunReport(ReportDelegate rd) {
rd(1, "hello");
}
}
class Test {
static void TestReport(int a, string b) {
// ....
}
public static void Main(string[] args) {
Runner.RunReport(TestReport);
}
}
Instead of defining your own delegate types, you can use pre-defined ones based on Action<T1,T2,...> or Func<T1,T2,R>, depending on your need to return values from the reports.
Rather than storing the method name, you could store a delegate:
struct ReportInfo
{
public string Name { get; set; }
public Action Method { get; set; }
}
//...
MyArray[0] = new ReportInfo { Name = "Daily_Unload", Action = this.reportDailyUnload };
//...
if(this.cboSelectReport.Text == MyArray[i].Name)
{
MyArray[i].Method.Invoke();
}
Most people seem to prefer the alternative syntax where you can invoke a delegate as if it were a method, using a list of arguments in parentheses. I tend to avoid this, because it can be ambiguous whether the thing being invoked is a method or a delegate:
MyArray[i].Method();
In this case, we're invoking the delegate that is referred to by the Method property, but this code could also represent a call to a method called "Method". Confusing.
As for me, supporting simple switch is much easier than dealing with reflection, array of method names or delegates, and invoking that stuff:
switch (reportType)
{
case "Daily_Unload":
ReportDailyUnload();
break;
// ...
}
If all the methods share the same signature, one way would be to cache a delegate:
// initialize, maybe in a constructor
Dictionary<string, Action> nameDelegateMapping = new Dictionary<string, Action>();
// setup the delegates
nameDelegateMapping.Add("Daily_Unload", reportDailyUnload);
// ... add more methods here.
// later
string methodName = this.cboSelectReport.Text;
Action action;
if (nameDelegateMapping.TryGetValue(methodName, out action))
{
action();
}
else
{
// tell user the method does not exist.
}
Yes, what you are talking about is reflection. Here is an article on how to invoke a method. There is a lot you can find on reflection using google.
Add a delegate property to your struct (e.g. of type Action) then just invoke this delegate when you need it. Just set this property to the method you want to call when instantiating the struct instances.
Using a delegate and dictionary<string, delegate>
void Main()
{
var reports = new Dictionary<string, Report>
{
{"Daily_Unload", ReportDailyUnLoad}
};
var report = "Daily_Unload";
reports[report]();
}
delegate string Report();
string ReportDailyUnLoad()
{
return "daily unload report";
}