I have a problem on having called a generic method, I have searched very much and do not find a solution, this one is my mistake.
And I do not have knowledge of I am doing badly,
The type arguments for method 'FormGasolineUserControl.loadList<T>(list<T>,string)' cannot be inferred from the usage. try specifying the type arguments expliciy.
this is my code:
This chunk of code where I obtain the error
private void loadDataForm()
{
try
{
DateTime dateNow = DateTime.Now;
// Call Services WPF
var QueryBD = services.LoadDataFormGasoline(1, (int)ETax.Gasoline);
if (QueryBD.Company != null)
{
day.Value = dateNow.Day.ToString();
month.Value = dateNow.Month.ToString();
year.Value = dateNow.Year.ToString();
anioGravable.Value = dateNow.Year.ToString();
peridoGravable.Value = PeriodoGravable(dateNow).ToString();
//Error call Method
loadList( QueryBD.QualityDeclarate, QualityDeclarate.Name.ToString());
loadList( QueryBD.TypeDeclarate, TypeDeclarate.Name.ToString());
}
}
catch (Exception)
{
throw;
}
}
And this one is the method:
public void loadlist<T>(List<T> lista,string nameControl)
{
try
{
switch (nameControl)
{
case "TypeDeclarate":
TypeDeclarate.Items.Add(new ListItem("Select..."));
foreach (var name in lista)
{
TypeDeclarate.Items.Add(new ListItem(name.ToString()));
}
break;
case "QualityDeclarate":
QualityDeclarate.Items.Add(new ListItem("Select..."));
foreach (var name in lista)
{
QualityDeclarate.Items.Add(new ListItem(name.ToString()));
}
break;
}
}
catch (Exception)
{
throw;
}
}
My principal aim is to be able to load the usercontrol dynamicamente by means of lists consulted in database.
help me plis...
This code could be improved in a great many ways.
It should not be generic.
It could be refactored into smaller methods that are more clear.
The naming conventions do not follow C# conventions.
It takes a list but only enumerates the elements
It really operates on sequences of strings.
The try-catch is useless.
Let's fix it.
private void AddItemsToCollection(IEnumerable<string> names, IList<ListItem> items)
{
items.Add(new ListItem("Select..."));
foreach (var name in names)
items.Add(new ListItem(name));
}
See how simple that is? Make simple methods that do one thing well. Now we use that helper to make other simple methods:
private void AddItemsToCollection(IEnumerable names, IList<ListItem> items)
{
AddItemsToCollection(names.Cast<object>().Select(n => n.ToString(), items);
}
Again, super simple. One line. Let's make more one-liners:
public void AddTypeDeclarateItems(IEnumerable names)
{
AddItemsToCollection(names, TypeDeclarate.Items);
}
SO EASY. Do it again.
public void AddQualityDeclarateItems(IEnumerable names)
{
AddItemsToCollection(names, QualityDeclarate.Items);
}
And now our method is simple:
public void AddItemsToCollection(IEnumerable names, string control)
{
switch (control)
{
case "TypeDeclarate":
AddTypeDeclarateItems(names);
break;
case "QualityDeclarate":
AddQualityDeclarateItems(names);
break;
}
}
Your code will get easier to understand, easier to make correct, easier to debug, if you simplify it so that every method does one thing.
Alternative solution: move the switch into a helper:
IList<ListItem> GetItems(string control)
{
switch (control)
{
case "TypeDeclarate":
return TypeDeclarate.Items;
case "QualityDeclarate":
return QualityDeclarate.Items;
}
throw new SomeException(...);
}
And now our method is:
public void AddItemsToCollection(IEnumerable names, string control)
{
AddItemsToCollection(names, GetItems(control));
}
Again, see what happens when you make every method do one thing? Every method gets really easy to understand, and highly likely to be correct.
This is the correct way to call this method:
...
loadlist<string>(QueryBD.myListOfStrings, "nameControl");
loadlist<int>(QueryBD.myListOfInts,"nameControl");
...
But, I guess that maybe the problem is inside the class that contains the method
void loadlist<T>(List<T> lista,string nameControl).
Aswer this question: What is T? I mean, in a class declaration we have many possibilities.
We can set T argument like a class: public MyClass<T> where T : class;
A struct: public MyClass<T> where T : struct; A class that has a public constructor public MyClass<T> where T : new(),...
See all possibilities: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters
So, let's imagine that T is a class that must implements an interface and you're passing a class that doesn't implement it, so you'll not have success.
Related
using these classes
public class Parent
{
public int parentInt;
}
public class Child: Parent
{
public string childString;
public Child(string passedString, int passedInt)
{
childString = passedString
parentInt = passedInt
}
}
I want to write a function that does stuff like this:
public static void DoSomething(Parent passedParent, Type passedChildType)
{
ScreenRecorder.Start()
//print all of parents properties
//print all of the specific child's properties if possible
}
I want this function to be able to handle any type of child I create in the future, How can I make it so that I can dynamically rebuild the child's properties inside the function?
Here is an example of the method being called:
public static int dostuff(string s)
{
int functionReturnValue = 0;
switch (s)
{
case "":
functionReturnValue = 0;
break;
case "7/8":
functionReturnValue = 14;
break;
case "15/16":
functionReturnValue = 15;
break;
default:
Child ex = new Child("Blue", 1);
Library.Handler.Process(ex, typeof(Child));
break;
}
return functionReturnValue;
}
What can I pass in or do inside the Dosomething method to rebuild the child object attributes?
To answer the question that is actually being asked. Yes you can "rebuild" an object on the other side.
See this code for an example:
public class Parent
{
int thing = 1;
}
public class Child1 : Parent
{
public string name;
public Child1(string p)
{
this.name = p;
}
}
public class Child2 : Parent
{
public string name;
public Child2(string p)
{
this.name = p;
}
}
In this function we setup a Child1 object and pass it to another function.
private void SetupStuff
{
Child1 x = new Child1("Bob");
DoStuff(x);
}
Here we can receive and "rebuild it"
private void DoStuff(Parent obj)
{
Child1 rebuiltObject = ((Child1)obj);
MessageBox.Show(rebuiltObject.name);
}
The MessageBox will show "Bob"
Please note however that this will cause a runtime error:
private void DoStuff(Parent obj)
{
Child2 rebuiltObject = ((Child2)obj);
MessageBox.Show(rebuiltObject.name);
}
It is smart enough to prevent you from rebuilding your object as something it never was.
Method 1: Message Dictionaries
The best way to do this, I'd say, would be to replace both the Parent and Child classes with a simple dictionary, so you can include any number of properties as needed. This can be easily iterated over and include whatever information you need in your messages.
Method 2: Interfaces
Rather than making your Process method take a type as a parameter, I'd suggest making it generic - constrained to IParent. The call becomes:
Library.Handler.Process(ex);
Declared as:
public void Process<TMessageType>(T message) where TMessageType : IParent
{
ScreenRecorder.Start();
message.Print();
}
Your IParent interface would, as above, include a method called Print, which in your base parent class would print the ParentInt property you defined above, formatted as needed. Child would then look the same as it does now, with an additional override to Print.
This allows you to keep your current structure for the most part.
Method 3: Reflection
The third, worst way would be to use your current structure as is and reflect on the properties. Your DoSomething method will become a mess, and perhaps rather slow (maybe unimportant). This would require the least redesign, but at the cost of being rather terrible code.
Any of these approaches will do, but I really have to stress that the order they're presented in has a lot to do with their quality.
First off, I totally apologize for the title, I don't know what the heck to put, it's such a confusing concept to really explain in a title, so bear with me.
public class fido
{
public void foo(process proc)
{
if (/* comparing by time */)
{
if (proc[parent].time < proc[child].time)
{
//do something
}
}
else if (/* comparing by priority */)
{
if (proc[parent].priority < proc[child].priority)
{
//do something
}
}
}
}
How do I go about shortening this? I was hoping it could be as simple as using a "defined" member through the parameter of foo().
For example
public class fido
{
public void foo(process proc, something mem)
{
if (/* comparing by time */)
{
if (proc[parent].mem < proc[child].mem)
{
//do something
}
}
}
}
Then I would use something like
foo(processA, time); // If I want to use time member
foo(processB, priority); // Or if I want to use priority member
I know the previous codes are 100% incorrect, but I hope you understand what I'm getting at.
I'm just trying to shorten the code because what I have is a priority queue class that uses heap and everything to prioritize values, however I need to use the class for multiple types of values, such as time and priority. I definitely do not want to create a duplicate class (totally not beneficial), I'm looking for a way I can shorten it. Does anybody know the best way?
You could pass an enum as a parameter in your method.
public class Fido
{
public void foo(Process proc, Options options)
{
if (options == Options.Time)
{
//Do time work
}
else if (options == Options.Priority)
{
//Do priority work
}
}
}
public enum Options
{
Time,
Priority
}
Note that a passing a bool instead of an enum would work here as well. It just makes things a bit less readable.
In my program I have a listbox that when the user double clicks an object it looks to a switch statement to see what event should occur. As the list begins getting larger I'm curious if there is a way to avoid having to maintain the list of objects in 2 places (once in a list to Add to the listbox, and once in the switch statement.
Is there a way to index/read/store the various Cases of my switch statement, then add them as objects to my listbox?
Example: (doesn't work, just a theory)
Switch (n)
ForEach (Case c in Cases)
{
arrayCases.Add(c);
}
listbox.Items.AddRange(arrayCases);
EDIT:
Going on the Dictionary recommendations I now have:
public void SetDictionary()
{
//add entries to the dictionary
dict["cat"] = new Action(Cat);
dict["dog"] = new Action(Dog);
//add each dictionary entry to the listbox.
foreach (string key in dict.Keys)
{
listboxTest.Items.Add(key);
}
}
//when an item in the listbox is double clicked
private void listboxTest_DoubleClick(object sender, EventArgs e)
{
testrun(listboxCases.SelectedItem.ToString());
}
public void testrun(string n)
{
//this is supposed to receive the item that was double clicked in the listbox, and run it's corresponding action as defined in the dictionary.
var action = dict[n] as Action action();
}
I believe that my code above is mostly correct and that I'm understanding it, however the action line:
var action = dict[n] as Action action();
Shows an error stating 'action' is expecting a ';'. Is my logic here accurate? If so, why is the action call incorrect?
Dictionary<string, Action> is the way to avoid. Dictionary.Keys becomes ListBox.Items.
switch(n) becomes
var action = dict[n] as Action
action();
I suggest to move your operations into separate classes. Create a base class for your operations like the following one. I added a field for the form because you probably have to interact with your form. You can also pass in other objects if required.
internal abstract class Operation
{
protected readonly MyForm form = null;
protected Operation(MyForm form)
{
this.form = form;
}
public abstract String DisplayName { get; }
internal abstract void Execute();
}
Then derive one class for each operation.
internal sealed class DoThis : Operation
{
internal DoThis(MyForm form) : base(form) { }
public override String DisplayName
{
get { return "Do this!"; }
}
internal override void Execute()
{
// Code to do this. You can use this.form to interact with
// your form from this operation.
}
}
internal sealed class DoSomethingElse : Operation
{
internal DoSomethingElse(MyForm form) : base(form) { }
public override String DisplayName
{
get { return "Do something else!"; }
}
internal override void Execute()
{
// Code to do something else.
}
}
Now you can add all your operations to the list box
this.lsitBox.Items.Add(new DoThis(this));
this.lsitBox.Items.Add(new DoSomethingElse(this));
and set the display member property.
this.listBox.DisplayMember = "DisplayName";
Finally execute the selected operation in the event handler.
((Operation)this.listBox.SelectedItem).Execute();
This pattern gives clean separation between all your operations and makes future extensions easy and clean. For example you could add a property CanExecute to all operations if you have to check if a operation is currently available. Or if you have to support localization it is easy to add logic for presenting the name of the operation in the current UI language.
Another scenario that is easily supported is if you have some code common to all operations for example logging, security checks, performance measuring and things like that.
internal abstract class Operation
{
protected readonly MyForm form = null;
protected Operation(MyForm form)
{
this.form = form;
}
public abstract String DisplayName { get; }
protected abstract void ExecuteCore();
internal void Execute()
{
Logger.Log("Executing operation " + this.DisplayName);
try
{
this.ExecuteCore();
Logger.Log("Executing operation " + this.DisplayName + " succeeded.");
}
catch (Exception exception)
{
Logger.Log("Executing operation " + this.DisplayName + " failed.", exception);
throw;
}
}
}
Note that you now have to override ExecuteCore() instead of Execute().
One final thought - using an interface IOperation instead or in combination with the abstract base class may be helpful, too. This removes the need that all operation inherit from the same base class because this might sometimes be inconvenient. But I omitted this to not overengineere this even more.
You can't* enumerate case of switch with normal code.
What you can do instead is to replace switch with map of "action name" to "action handler" and than you'll be able to reuse this map for list of action names listbox. See Tilak's answer for sample.
*) If you are really inquisitive you can enumerate choices of switch. C# code is transformed to IL and IL can be read with code. So you can get IL for a method, write (or get existing - Parser for C#) parser for IL and find implementation of switch inside the method, pick all cases. You can even go straight to C# source at build time - but it is even more involved than IL parsing.
Yes there is a way to do this by making a dictionary of lambdas.
void Main()
{
// set up your dictionary
Dictionary<string,Action> myList = new Dictionary<string,Action> {
{ "one", () => { Console.WriteLine("One function"); } },
{ "two", () => { Console.WriteLine("Two function"); }},
{ "three", () => { Console.WriteLine("Three function"); }}
};
// do a "switch" (that is invoke a function that corresponds to a name)
myList["one"]();
// loop the list of keys (that is get a list of all the names)
foreach (string key in myList.Keys)
Console.WriteLine(key);
}
the output of this program:
One function
one
two
three
Also note -- you can add to this "switch" dynamically like this (which is cool and something you can't do with a classical switch statement.)
myList.Add("four",() => { Console.WriteLine("Four function is dynamic"); });
It sounds to me like the number of cases in your switch are going to change a lot. If this is true, then you might want to consider using a mechanism other than a switch statement. Perhaps you want to do something like Alexi Levenkov suggests, and then iterate a list of the stored Action Names and execute the associated handler. This way you will avoid having to add the action name to the action map and then add it to the switch.
So I've got a whole bunch of options, every different page/tab can have their own local options. We'll have maybe 10-15 pages tabs open tops. I need to implement a way to show the global defaults, weather the all the tabs have consistent values. I'm working on the model/viewmodel portion of a WPF app.
I'd love to find a way that is more elegant since I'm having to cut and past roughly the same code 20+ times and just change property names. Maybe this is the problem Dynamics solve, but right now this feels both wrong and painful.
Here is an example of my current solution:
public class Foo
{
private bool fooVar1;
private bool fooVar2;
//lots of these
private decimal fooVar23;
public Foo()
{
}
public bool FooVar1
{
get;
set;
}
//you get the picture...
}
public class FooMonitor
{
private Foo defaultFoo;
private List<Foo> allFoos;
public FooMonitor(Foo DefaultFoo)
{
defaultFoo = DefaultFoo;
}
public void AddFoo(Foo newFoo)
{
allFoos.Add(newFoo);
}
public void AddFoo(Foo oldFoo)
{
allFoos.Remove(oldFoo);
}
public bool IsFooVar1Consistent
{
get
{
Foo[] tempFoos = allFoos.ToArray();
foreach (Foo tempFoo in tempFoos)
{
if (tempFoo.FooVar1 != defaultFoo.FooVar1) return false;
}
return true;
}
}
}
Or am I approaching this problem entirely incorrectly.
As I'm writing this question (After about 2000 lines of code) I'm thinking of how I read that WPF itself implements Dictionary look ups that crawl up to the parent to see if a Property is present and what the value should be.
Well, for a start you are defining both backing fields which will never be used and automatic properties. This is enough for a simple bool property:
public bool FooVar1 { get; set; }
No need for the private field. This greatly reduces the number of lines in your example.
I'd love to find a way that is more
elegant since I'm having to cut and
past roughly the same code 20+ times
and just change property names.
Code generators exist for exactly this purpose. But if you don't want to go that route, you can shorten your code to this:
return allFoos.All(foo => foo.FooVar1 == defaultFoo.FooVar1);
I'm not quite sure what the question is, but if you're looking for some way to unify the IsFoorVarXConsistent code, you could do it using reflection or by passing in an expression:
public bool IsConsistent(Func<Foo, bool> property)
{
foreach (Foo tempFoo in allFoos)
{
if (property(tempFoo) != property(defaultFoo))
return false;
}
return true;
}
Called like this:
bool is1Consistent = IsConsistent(f => f.FooVar1);
As shown this will only work for boolean properties. To extend it to other types, we can make it generic in the property type. However, in this case we cannot use != to test for inequality because not all types define a != operator. Instead we can use the .Equals method and the ! operator:
public bool IsConsistent<T>(Func<Foo, T> property)
where T : struct
{
foreach (Foo tempFoo in allFoos)
{
if (!property(tempFoo).Equals(property(defaultFoo)))
return false;
}
return true;
}
The where T : struct clause restricts this to value types like int, bool and decimal. In particular it will not work on strings. Removing the where constraint allows it to work on strings and other reference types, but creates the possibility of property(tempFoo) being null, which would cause a NullReferenceException when we called .Equals on it. So if you remove the value types constraint then you will need to add error handling for this scenario.
Alright, i dont know how to explain it well.. but i have a switch statement,
string mystring = "hello";
switch(mystring)
{
case "hello":
break;
case "goodbye":
break;
case "example":
break;
}
of course this is an example, and in the real situation, there will be different things happening for each case.
ok, hope you get the point, now, doing this manually is impossible, because of the sheer number of different case's. i need to respectively create a list, of all the cases, so for instance.. for the above switch statement, i would need
string[] list = { "hello", "goodbye", "example" };
maybe could be done with a foreach some how i dont know, any help would be greatly appreciated.
also, any working codes provided would be awesome!
edit:
people are asking for more detail, so here is how it works.
the user of the program, inputs a series of strings.
based on the string(s) they entered, it will do a few if's and else if's and throw back the new strings basically. i need to be able to be able to create a list, through the program, of all the options available to use. and i cant just make a list and hard code it in, because im always adding more case's to the statement, and i cant be going back and keeping a list up to date.
FOR VISUAL STUDIO:
if mystring is an enum instead of a string, in visual studio, if you type "switch" [TAB] "mystring" [ENTER] it'll build the long switch for you with all the cases.
It depends on how clever you want to get... You could create a custom attribute that attaches to a method with the string that method should handle. Then, instead of a switch statement, you would just find the attribute with your desired value and execute it.
using System;
using System.Reflection;
namespace ConsoleApplication1 {
[AttributeUsage(AttributeTargets.Method)]
internal class ProvidesAttribute : Attribute {
private String[] _strings;
public ProvidesAttribute(params String[] strings) {
_strings = strings;
}
public bool Contains(String str) {
foreach (String test in _strings) {
if (test.Equals(str)) {
return true;
}
}
return false;
}
}
internal class Program {
[Provides("hello", "goodbye")]
public void HandleSomeStuff(String str) {
Console.WriteLine("some stuff: {0}", str);
}
[Provides("this")]
public void HandleMoreStuff(String str) {
Console.WriteLine("more stuff: {0}", str);
}
public void HandleString(String str) {
// we could loop through each Type in the assembly here instead of just looking at the
// methods of Program; this would allow us to push our "providers" out to other classes
MethodInfo[] methods = typeof(Program).GetMethods();
foreach (MethodInfo method in methods) {
Attribute attr = Attribute.GetCustomAttribute(method, typeof(ProvidesAttribute));
ProvidesAttribute prov = attr as ProvidesAttribute;
if ((prov != null) && (prov.Contains(str))) {
method.Invoke(this, new Object[] { str } );
break; // removing this enables multiple "providers"
}
}
}
internal static void Main(String[] args) {
Program prog = new Program();
foreach (String str in args) {
prog.HandleString(str);
}
}
}
}
Once you have the framework, you wouldn't need to alter the HandleString() code, just add the methods you want to take care of and set the Provides attribute on them. If you wanted to extend the idea a little further, you could create multiple classes to handle a wide variety of strings, then loop through each type in your assembly looking for the Provides attribute.
EDIT this has the added benefit that you can define multiple methods that act on the same string (by removing the break in the loop logic).
I'm note sure what you are trying to do, but you might be able to use a dictionary.
Dictionary<string, int> lookupTable = new Dictionary<string, int>();
lookupTable.Add("hello", 1);
lookupTable.Add("goodbye", 2);
lookupTable.Add("example", 3);
int output = lookupTable["hello"];
You wouldn't need to have code to add each individual entry. You could read in the keys and values from a file, loop though them and populate the dictionary.
If you explain more about what you are trying to do, we could give you more specific advice.
By proper refactoring (your hypothetical example) you can make sure that out of your sheer number of cases, there will be a lot of them that can call the same sub routine with their string parameter.
In many of these scenarios, you may not even need a huge switch statement, but just parameterize one sub routine that can handle them.
Without a concrete example of what you want to do in the case statements, it is hard to come up with a concrete answer.
You appear to be trying to extract "command strings" from your code, so that you can automatically update the list of available commands in your user documentation. I think this will not gain you much, as you will still need to manually document what each command does.
That being said, the following powershell command will extract the data you want from test.cs:
type test.cs|select-string 'case "(.*)"'|foreach {$_.Matches[0].Groups[1].Value}
Switch statements evaluate on constants, so the case statements won't work with variables. Perhaps you should consider using a Dictionary<> and branching based on that. But without any more insight into the problem you're solving, there's little point in saying anything more.
Create an abstract class, call it something like StringHandler. Give it 2 abstract methods, 1 to check whether the handler can handle the string, then the other to do the processing. Something like:
public abstract class StringHandler
{
public abstract bool CanProcess(string input);
public abstract void Process();
}
public class HelloStringHandler : StringHandler
{
public override bool CanProcess(string input)
{
return input.Equals("hello");
}
public override void Process()
{
Console.WriteLine("HELLO WORLD");
}
}
Then in your main class you can do a simple loop with a list of all known handlers, like
List<StringHandler> handlers = new List<StringHandler>();
handlers.Add(new HelloStringHandler());
string myString = "hello";
foreach (StringHandler handler in handlers)
{
if (handler.CanProcess(myString))
{
handler.Process();
break;
}
}
All this can be optimised/improved obviously, but I hope you get the picture?
I am very rusty at c#, but this was a fun little exercise. The following code is not very clean, but will do what you asked. You will want to add more checks, use the variables better and add more logic, but this should help you get going in the right direction.
var newfile = System.IO.File.CreateText("newcode.txt");
newfile.Write("string[] list = { ");
using (var file = System.IO.File.OpenText("code.txt"))
{
bool bFirst = true;
while (!file.EndOfStream)
{
String line = file.ReadLine();
if (line.Contains("case ") && line.EndsWith(":"))
{
line = line.Replace("case", " ");
line = line.Replace(":", " ");
line = line.Trim();
if (bFirst == false)
{
newfile.Write(", ");
}
bFirst = false;
newfile.Write(line);
}
}
}
newfile.WriteLine(" };");
newfile.Close();
Good luck!
Inspired by #Jheddings answer, I came up with this. Maybe it's over the top, but at least I had fun figuring it out:
Main benefits over jheddings solution:
Uses extension methods, no utility class instance needed.
Reflection lookup of all candidate methods is done only once, right before the first string is evaluated. Afterwards, it is a simple lookup and invoke.
Even simpler usage
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
namespace StringSwitcher
{
class Program
{
static void Main(string[] args)
{
"noAction".Execute(); //No action, since no corresponding method defined
"Hello".Execute(); //Calls Greet method
"world".Execute(); //Calls Shout method
"example".Execute(); //Calls Shout method
Console.ReadKey();
}
//Handles only one keyword
[Keywords("Hello")]
static public void Greet(string s)
{
Console.WriteLine(s + " world!");
}
//Handles multiple keywords
[Keywords("world", "example")]
static public void Shout(string s)
{
Console.WriteLine(s + "!!");
}
}
internal static class ActionBrokerExtensions
{
static Dictionary<string, MethodInfo> actions;
static ActionBrokerExtensions()
{
//Initialize lookup mechanism once upon first Execute() call
actions = new Dictionary<string, MethodInfo>();
//Find out which class is using this extension
Type type = new StackTrace(2).GetFrame(0).GetMethod().DeclaringType;
//Get all methods with proper attribute and signature
var methods = type.GetMethods().Where(
method => Attribute.GetCustomAttribute(method, typeof(KeywordsAttribute)) is KeywordsAttribute &&
method.GetParameters().Length == 1 &&
method.GetParameters()[0].ParameterType.Equals(typeof(string)));
//Fill the dictionary
foreach (var m in methods)
{
var att = (Attribute.GetCustomAttribute(m, typeof(KeywordsAttribute)) as KeywordsAttribute);
foreach (string str in att.Keywords)
{
actions.Add(str, m);
}
}
}
public static void Execute(this string input)
{
//Invoke method registered with keyword
MethodInfo mi;
if (actions.TryGetValue(input, out mi))
{
mi.Invoke(null, new[] { input });
}
}
}
[AttributeUsage(AttributeTargets.Method)]
internal class KeywordsAttribute : Attribute
{
private ICollection<string> keywords;
public KeywordsAttribute(params String[] strings)
{
keywords = new List<string>(strings);
}
public ICollection<string> Keywords
{
get { return keywords; }
}
}
}
Apologies for any strange rendering, for some reason the syntax highlighting chokes on the code :-(