I am trying to create code for a DLL that will manage, create and return variables to the program using it. I could just not use a DLL but I want my code to be less cluttered and also to save time in "if var == whatever" statements.
Here is my code so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JERK_mgr
{
class Program
{
static void Main(string[] args)
{
// DLL file that makes managing, reading and creating variables easier
// >>J03L<<
// v0.0-initial
newVar("", "");
Console.WriteLine(TESTVAR);
}
internal static void newVar(string name, object value);
{
public const string TESTVAR = "hey it actually worked! :D";
}
}
}
At this moment in time I don't intend for it to do anything but the following:
- Be called from Main
- create a variable that can then be accessed through Main and any other methods.
I am aware that I may be using internal incorrectly here, but it was just an attempt at getting it to work and just used to be public.
What then happens is I get an error at
internal static void >>newvar<<(string name, object value)
saying it must declare a body, but this isn't my main problem, atleast as far as I know.
I then get an error at
internal static void newvar(string name, object value)
>>{<<
I also notice that
internal static void newVar(string name, object value);
{
public const string TESTVAR = "hey it actually worked! :D";
>>}<<
when hovered over or selected, says it matches up to
class Program
{
So I ask, how do I have a function that is not the Main function declare a variable that is accessible throughout any other function, including the Main function?
EDIT1: I think I have found a way to make the variables how I want them, but now I am facing the problem of mismatching curly brackets even though they should match (can be seen at https://imgur.com/a/scBYuaH)
I think the question you are really asking is "how do I write a function that defines global variables?" If that really is your question then the answer is C# (any many other object oriented languages) won't allow it. (unless maybe you use some twisted kind of reflection code.)
remove ; after (string name, object value)
and it's a function you can't declare a public const value in the function try to move to outside.
class Program
{
public string TESTVAR = "hey it actually worked! :D";
internal static void newVar(string name, object value)
{
}
static void Main(string[] args)
{
//....
}
}
how do I have a function that is not the Main function declare a
variable that is accessible throughout any other function, including
the Main function?
While you can't dynamically create variables, you can do something like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp29
{
class Program
{
public static dynamic Vars = new System.Dynamic.ExpandoObject();
static void AddorUpdateVar(string name, object value)
{
var vd = (IDictionary<string, object>)Vars;
vd[name] = value;
}
static void Main(string[] args)
{
AddorUpdateVar("Hello", 213);
var a1 = Vars.Hello;
AddorUpdateVar("Hello", "World");
var a2 = Vars.Hello;
Vars.Hello = new int[] { 7, 3 };
var a3 = Vars.Hello;
}
}
}
Related
First , I'm a C++ dev and new to C# , Sorry for this simple question.
I'm creating a wrapper for my native library.
I want to pass a value in a class and edit it from some other function in class , like pointers in C++ , I found out it can be done with unsafe mode but I need to do it without unsafe and I'm sure it's possible.
Here's my code :
Main Console
namespace ConsoleApp2
{
class Program
{
[STAThread]
static void Main(string[] args)
{
string DATA_VALUE = "Not Set Yet";
new Data_Picker_Form(DATA_VALUE).ShowDialog();
Console.WriteLine("Value is {0}", DATA_VALUE);
Console.ReadKey();
}
}
}
Form Code
using System;
using System.Windows.Forms;
namespace ConsoleApp2
{
public partial class Data_Picker_Form : Form
{
object data_in_obj;
public Data_Picker_Form(string data_in)
{
InitializeComponent();
data_in_obj = data_in;
}
private void button1_Click(object sender, EventArgs e)
{
string data_in_new = data_in_obj as string;
data_in_new = "OUTPUT_VALUE";
this.Close();
}
}
}
it's not working unfortunately , so I need to pass my string , int and etc. value to a new form , in initializing form creates a instance [like pointer] to original string and it can accessible from other functions ins class like button click.
thanks.
You already have a reference (sort of like a pointer), and that is your problem (well, half of it anyways).
string data_in_new = data_in_obj as string;
Says to create a variable that holds a string reference (as strings are immutable reference types) and copy the reference data_in_obj currently has to it. When you then reassign data_in_new it of course doesn't affect any other variable (just like it wouldn't in C++).
Because strings are immutable, there is no way for that code to affect other things that point to that string (passing by reference aside, but this is about variables/members). You need to store it in a simple struct or class so that everyone is pointing at an object that holds the current string reference, and can be updated.
Same idea with your int, it is actually a value type so any copy will copy the actual value, you can't change a different variable through it. You need a wrapper class so that each user is pointing at the same object.
What about setting up a simple get and set function since you are already Initializing your Form?
In Your Form:
private string data_in_new = "";
public Data_Picker_Form(string DATA_VALUE)
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Data_in_new = "OUTPUT_VALUE";
Close();
}
public string Data_in_new
{
get
{
return data_in_new;
}
set
{
data_in_new = value;
}
}
And in your Console:
class Program
{
static void Main(string[] args)
{
string DATA_VALUE = "Not Set Yet";
Data_Picker_Form D_P_T = new Data_Picker_Form(DATA_VALUE);
D_P_T.ShowDialog();
DATA_VALUE = D_P_T.Data_in_new;
Console.WriteLine("Value is {0}", DATA_VALUE);
Console.ReadKey();
}
}
This Way you can access you value at any desired point in the project.
I have 2 form applications. One form application is calculating values and putting them in the array. The second form application takes these values and checks them, according to there value it draws something. According to the debugger, the 2 by 2 array is empty when it comes to the second form.
In reality, the two name spaces are in different files in visual studio and the using statements are all repeated for the second form window.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public const int SIZEX = 656;
public const int SIZEY = 656;
public static int[,] xinteracting = new int[SIZEX, SIZEY]; //Tells you the points at which it interacts with the different objects
public static void Main(string[] args)
{
xinteracting [0,0] = 1;
//Your code goes here
//Console.WriteLine("Hello, world!");
}
}
}
/*Second form window represented from here*/
namespace Hello
{
public class Yollow
{
public static void Main(string[] args)
{
Program old = new Program();
int temp = old.xinteracting[0,0];
Console.WriteLine( temp);
}
}
}
In my opinion, when you create an instance of class Program, xinteracting is created, too, but Main method do not run, so that you receive an empty array.
My solution:
Create constructor in class Program => set xinteracting [0,0] = 1;
Because that array is static, you can get/set value directly from anywhere. Just call Program.xinteracting[0,0] = 1 to set or var value=Program.xinteracting[0,0]; to get
I have a list and I am trying to find a particular element and then I want to edit that element.
storage.First(item => item.dirty == true).dirty = false;
However this doesn't appear to work since I am guessing First is creating another list and populating it. Is there a function to do what I am I am trying to do?
Here is the data type I am using:
class BaseRegister {
public bool dirty {set;get;}
}
List <BaseRegister> storage = new List <BaseRegister> ();
This will work, but only if your type (that contains .dirty) is a class.
If this is a struct, you will not be able to mutate the struct this way. With a struct, you'd need to replace the entire struct in the collection, which is very difficult using the LINQ extensions, as they are designed for queries, not edits.
If the type (of storage) implements IList<T>, such as List<YourClass>, you could use:
int index = storage.FindIndex(item => item.dirty);
var item = storage[index];
item.dirty = false;
storage[index] = item;
Note that it's messy, but mostly because it has to completely reset the value of the struct in the list.
This, btw, is partly why mutable structs are a bad idea. If you find that this is a pattern you think you need with your type, you may want to consider a class. In general, any item that's going to have a "dirty" flag is likely mutable, and as such, should be a class and not a struct.
There must be something else wrong with your program which is confusing you. For the avoidance of doubt, here is a complete program using your data types. The output is:
---Before---
True
False
True
---After---
False
False
True
The code is:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace ConsoleApplication40 {
internal class Program {
private static List<BaseRegister> storage=new List<BaseRegister>();
private static void Main(string[] args) {
storage.Add(new BaseRegister {dirty=true});
storage.Add(new BaseRegister {dirty=false});
storage.Add(new BaseRegister {dirty=true});
Dump("---Before---");
storage.First(item => item.dirty==true).dirty=false;
Dump("---After---");
}
private static void Dump(string title) {
Debug.WriteLine(title);
foreach(var br in storage) {
Debug.WriteLine(br.dirty);
}
}
private class BaseRegister {
public bool dirty { set; get; }
}
}
}
If item is a reference type, this should change the dirty property/field.
If item is a value type, First returns a copy, and this should not even compile.
First is not creating a list, it returns the first item in the sequence that fulfills the condition.
What i am trying to achieve here is a bit tricky. Let me brief on a little background first before going ahead.
I am aware that we can use a enum as a type to a parameter of a method. For example I can do something like this (a very basic example)
namespace Test
{
class DefineEnums
{
public enum MyEnum
{
value1 = 0,
value2 = 1
}
}
class UseEnums
{
public void UseDefinedEnums(DefineEnums.MyEnum _enum)
{
//Any code here.
}
public void Test()
{
// "value1" comes here with the intellisense.
UseDefinedEnums(DefineEnums.MyEnum.value1);
}
}
}
What i need to do is create a dynamic Enum and use that as type in place of DefineEnums.MyEnum mentioned above.
I tried the following.
1. Used a method which i got from the net to create a dynamic enum from a list of strings. And created a static class which i can use.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
namespace Test
{
public static class DynamicEnum
{
public static Enum finished;
static List<string> _lst = new List<string>();
static DynamicEnum()
{
_lst.Add("value1");
_lst.Add("value2");
finished = CreateDynamicEnum(_lst);
}
public static Enum CreateDynamicEnum(List<string> _list)
{
// Get the current application domain for the current thread.
AppDomain currentDomain = AppDomain.CurrentDomain;
// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName aName = new AssemblyName("TempAssembly");
AssemblyBuilder ab = currentDomain.DefineDynamicAssembly(
aName, AssemblyBuilderAccess.RunAndSave);
// Define a dynamic module in "TempAssembly" assembly. For a single-
// module assembly, the module has the same name as the assembly.
ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
// Define a public enumeration with the name "Elevation" and an
// underlying type of Integer.
EnumBuilder eb = mb.DefineEnum("Elevation", TypeAttributes.Public, typeof(int));
// Define two members, "High" and "Low".
//eb.DefineLiteral("Low", 0);
//eb.DefineLiteral("High", 1);
int i = 0;
foreach (string item in _list)
{
eb.DefineLiteral(item, i);
i++;
}
// Create the type and save the assembly.
return (Enum)Activator.CreateInstance(eb.CreateType());
//ab.Save(aName.Name + ".dll");
}
}
}
Tried using the class but i am unable to find the "finished" enum defined above. i.e. I am not able to do the following
public static void TestDynEnum(Test.DynamicEnum.finished _finished)
{
// Do anything here with _finished.
}
I guess the post has become too long but i hope i have made it quite clear.
You'll either have to pass in an object, or create your method dynamically as well.
Might I ask why you can't just use an int for this? Seems like you're going to have to dynamically create a lot of code just to be able to pass it around as an enum.
As you create the enum dynamically, it doesn't exist until you run the code. As you can't use the type at compile time, you can't specify a parameter of that type. Creating an enum dynamically is only useful if you already have a method that expects an enum of some kind (but not any specific enum type), or if you also create the code that uses the enum dynamically.
What you can do with the enum instance is basically to get the string representation of a value, parse a string back to a value, and get a list of the defined values. This is a lot easier to accomplish with something like a Dictionary<int, string>.
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 :-(