Can't access the class I just created - c#

I hope this is a simple question. I'm building a simple console application in C#. I have a class:
using System;
using Filter;
public class Params
{
public string key;
public bool distinct;
public List<string> fields;
public string filter;
public int limit;
public int skip;
public bool total;
public List<Tuple<string, GroupType>> group;
public List<Tuple<string, OrderType>> order;
public Params()
{
key = "";
distinct = false;
fields = new List<string>();
filter = "";
group = new List<Tuple<string, GroupType>>();
limit = 0;
order = new List<Tuple<string, OrderType>>();
skip = 0;
total = false;
}
public void AddGroup(string field, GroupType type)
{
group.Add(new Tuple<string, GroupType>(field, type));
}
public void AddOrder(string field, OrderType type)
{
order.Add(new Tuple<string, OrderType>(field, type));
}
}
My program .cs class is:
namespace csharpExample
{
class Program
{
public static void Main(string[] args)
{
Params p = new Params();
Console.WriteLine("Test");
}
}
}
I want to use Params in my program.cs class where Main() is called. I thought I could simply use Params like above. I've also tried to do a using Params; both of these are errors in VS since it can't find the directive. I've also tried adding my own namespace: namespace MyNameSpace; around my Params class. When I do this I still am unable to do a using MyNameSpace; statement as it can't find it.
I just want to extract out a bunch of functions into a class that I can reuse. How do i call this class once it's created?
-Thanks
Thanks for the help.

If you want to access the Params object in the Main function, just add Params p = new Params (); to the Main function at the top.
Most likely your problem is that Main is static, meaning that it can't access other things that aren't static which are outside of it. If you declared Params in the Program class, unless you made it static, it can't be accessed in Main.

Are you talking about calling the constructor or the properties you are setting? You can set the class at the top of your base class and then call the instance of it. But since it is a static class you should probably use a helper method in the main.
namespace Example
{
public class Program
{
Params p = new Params();
string writefromParams() // I exist just to give the string back from params with a nonstatic method
{
return p.key;
}
static void Main(string[] args)
{
Program p2 = new Program(); // set up a new instance of this very class
Console.WriteLine(p2.writefromParams()); // get non static method from class
Console.ReadLine();
}
}
}

Related

Generic class and method binding with delegates(or not) for clean method expression

Lets say you have simple chained method but you are trying to access or set a value in a class property (internal/external doesnt matter). Using a Func seems to be working and finds the relation between generic class that is passed and access its properties correctly but i am not sure if its necessary.
Is there a way of setting the method variable cleanly as in Main method below since it is aware of the Generic class association without doing new Props().Property for example?
//sample console app
public class Props {
public string FirstProp = "lets say object";
public string SecondProp = "Pretend some other object";
}
public class Logic<T> where T : class, new()
{
private string outString { get; set; }
public Logic<T> GetPropertyValue(Func<T, object> propertySelector)
{
return this;
}
public Logic<T> GetLambda(Expression<Func<T, object>> propertySelector)
{
var breakpointCheck = propertySelector; //{x => x.SecondProp}
return this;
}
}
class Program
{
static void Main(string[] args)
{
var Test =
new Logic<Props>()
.GetPropertyValue(x => x.FirstProp) //dummy check
.GetLambda(x => x.SecondProp); //passed correctly {x => x.SecondProp}
var HowToGetThis =
new Logic<Props>()
.GetPropertyValue(FirstProp) // or GetPropertyValue(Props.FirstProp)
.GetLambda(x => x.SecondProp);
}
}

C# Pass any method as parameter

I'm making a networking application where I want to implement strongly typed RPC. As result I'd like to be able to pass methods no matter the parameters so I can get them and store them in a dictionary so I can construct request parameters properly as well once a packet arrive I am able to read it using the parameters the same remote method used
I'd like something like this:
Register(Enum key, [method with unknown parameters])
In C# 8.0 using generics and Delegate Constraint you can do something like this:
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
public class Program
{
public static void Main(params string[] args)
{
var app = new NetworkingApplication();
app.Register<Action<int, string>>(PacketType.Type1, Method1, 1, "string1 argument");
app.Register<Func<string, string>>(PacketType.Type2, Method2, "string2 argument");
app.OnPacketReceived(PacketType.Type1);
app.OnPacketReceived(PacketType.Type2);
}
public static void Method1(int arg1, string arg2)
{
Console.WriteLine($"Method1 Invoked with args: {arg1}, {arg2}");
}
public static string Method2(string arg1)
{
Console.WriteLine($"Method2 Invoked with args: {arg1}");
return "Foo";
}
}
public class NetworkingApplication
{
private readonly IDictionary<PacketType, DelegateInvoker> _registrations;
public NetworkingApplication()
{
_registrations = new Dictionary<PacketType, DelegateInvoker>();
}
public void Register<TDelegate>(PacketType packetType, TDelegate #delegate, params object[] args)
where TDelegate : Delegate
{
_registrations[packetType] = new DelegateInvoker(#delegate, args);
}
//invoke this when the packet is received
public void OnPacketReceived(PacketType type)
{
if (_registrations.TryGetValue(type, out var invoker))
{
invoker.Invoke();
}
}
private class DelegateInvoker
{
public DelegateInvoker(Delegate #delegate, object[] args)
{
Delegate = #delegate;
Arguments = args;
}
private Delegate Delegate { get; }
private object[] Arguments { get; }
public void Invoke()
{
Delegate.Method.Invoke(Delegate.Target, Arguments);
}
}
}
public enum PacketType
{
Type1,
Type2,
Type3
}
}
As mentioned above you can use MethodInfo, it belongs to the System.Reflection namespace. To do this, first get the Type type of the object like this:
var type = obj.GetType()
After this you can use var methods = type.GetMethods(). This will give you an MethodInfo[]. Search the element, using your favorite method for doing so. Such as Linq:
var method = methods.Where(it => it.Name == __yourName__).LastOrDefault();
*where yourName is the name of your method.
Now you have the method you are looking for. Get the parameters using
var parameters = method.getParameters();
And there are the parameters as ParameterInfo[].
From there you can get the type of each parameter using the parameter.ParameterType property.
This being said be very careful with Reflection, it is very, very powerful but can decrease performance heavily, when overused.
Have look at it System.Reflection namespace here .
You can now add the method to a collection, such as a dictionary:
var dictionary = new Dictionary<int,MethodInfo>();
dictionary.Add(1, method);
And retrieve it like this:
var method = dictionary[1];
To call the function you can user method.Invoke() and pass in the parameters as need.
EDIT:
If you would like to send the parameters as well as the function over a network. You could create a new class that serves as a DTO Data Transfer Object. This class could have as property an Array of parameters (ParameterInfo[]), the MethodInfo and anything else you want.
You could then serialize the object (maybe json) and send it to another system, that could then deserialize it, and Invoke the MethodInfo obj
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp
{
public class Program
{
public static void Main(params string[] args)
{
var app = new NetworkingApplication();
app.Register(PacketType.Type1, () =>
{
Console.WriteLine("Type1 Packet is received!");
});
}
}
public class NetworkingApplication
{
private readonly IDictionary<PacketType, Action> _registrations;
public NetworkingApplication()
{
_registrations = new Dictionary<PacketType, Action>();
}
public void Register(PacketType packetType, Action method)
{
_registrations[packetType] = method;
}
//invoke this when the packet is received
public void OnPacketReceived(PacketType type)
{
if (_registrations.TryGetValue(type, out var action))
{
action?.Invoke();
}
}
}
public enum PacketType
{
Type1,Type2,Type3
}
}

C# - rewrite delegate calls to Action<>

I have a need to wrap a number of functions with code that will pre-process input data for these functions ("Wrapper"). Here's the code written using delegates (the code is simplified as much as possible, while still functional and immediately compilable):
namespace ConsoleApp
{
class ClientContext
{
public int i = 1;
}
class SPRemoteEventProperties
{
}
class Program
{
public delegate void Del(ClientContext clientContext, SPRemoteEventProperties properties);
public static void Wrapper(Del f, ClientContext clientContext, SPRemoteEventProperties properties)
{
ClientContext newClientContext = new ClientContext
{
i = clientContext.i * 2
};
f(newClientContext, properties);
}
static void Main(string[] args)
{
Function1(new ClientContext(), new SPRemoteEventProperties());
Function2(new ClientContext(), new SPRemoteEventProperties());
Wrapper(Function1, new ClientContext(), new SPRemoteEventProperties());
Wrapper(Function2, new ClientContext(), new SPRemoteEventProperties());
Console.Read();
}
static void Function1(ClientContext clientContext, SPRemoteEventProperties properties)
{
Console.WriteLine("Function1: " + clientContext.i);
}
static void Function2(ClientContext clientContext, SPRemoteEventProperties properties)
{
Console.WriteLine("Function2: " + clientContext.i);
}
}
}
Now, to simplify the code I'd like to rewrite it using Action<> syntax and inline the functions' code. Here's what I tried to do, but I can't manage to write a correct and functioning program:
using System;
namespace ConsoleApp
{
class ClientContext
{
public int i = 1;
}
class SPRemoteEventProperties
{
}
class Program
{
Action<ClientContext, SPRemoteEventProperties> Act;
// error in next line =>
public static void Wrapper(Act f, ClientContext clientContext, SPRemoteEventProperties properties)
{
ClientContext newClientContext = new ClientContext
{
i = clientContext.i * 2
};
f(newClientContext, properties);
}
static void Main(string[] args)
{
Function1(new ClientContext(), new SPRemoteEventProperties());
Function2(new ClientContext(), new SPRemoteEventProperties());
// error in next 2 lines =>
Wrapper((new ClientContext(), new SPRemoteEventProperties()) => Console.WriteLine("Function1: " + clientContext.i));
Wrapper((new ClientContext(), new SPRemoteEventProperties()) => Console.WriteLine("Function2: " + clientContext.i));
Console.Read();
}
static void Function1(ClientContext clientContext, SPRemoteEventProperties properties)
{
Console.WriteLine("Function1: " + clientContext.i);
}
static void Function2(ClientContext clientContext, SPRemoteEventProperties properties)
{
Console.WriteLine("Function2: " + clientContext.i);
}
}
}
Can you help me correct this code?
I'm not sure i fully understand what you are trying to do, am i close?
public static void Wrapper(ClientContext clientContext, SPRemoteEventProperties properties, Action<ClientContext, SPRemoteEventProperties> action)
{
action(newClientContext, properties);
}
...
Wrapper( new ClientContext(), new SPRemoteEventProperties(),(context, properties) => Console.WriteLine("Function1: " + context.i));
The usage of Action is different than a delegate:
While the delegate syntax define a type declaration that you can use to define a variable, the Action syntax is already the type, and you can use it to create your variable.
I'm not sure i'm clear, but, following is the correct syntax to use:
public static void Wrapper(Action<ClientContext, SPRemoteEventProperties> f, ClientCo ...
An Action has the diamond notation (<>) after it, which is a sign that it is a generic type. Unlike delegate, it contains everything the compiler needs to make it type safe. This differs from delegate which is not really typed until you define a specific delegate, which tells the compiler the types of all the parameters. With the Action you just need to put the types into the diamond and voila, it is a complete type now.
Since the parameter name is always preceded by its type, your prototype should read like this:
public static void Wrapper(Action<ClientContext, SPRemoteEventProperties> f, ClientContext clientContext, SPRemoteEventProperties properties)
{
That is everything the compiler needs to know about what is going to be contained in that argument, type-wise.

How do I get the value from a variable which has it's values assigned in another class?

I need to have a class for Variables and Methods for the sake of manageability.
The problem is I am not sure how I can access the value of the variable assigned in the method class.
Here is the variable class, it just holds variables:
namespace Classes
{
class MyVariableClass
{
public string MyVariable { get; set; }
}
}
Here is the method:
I am calling an instance of the variable class in the method class so that I can assign the variable to the values of the method.
namespace Classes
{
class MyMethods
{
MyVariableClass myVarClass = new MyVariableClass();
public void DoSomeStuff(string myString1, string myString2)
{
myVarClass.MyVariable = (!string.IsNullOrEmpty(myString2)
? myString2 : "String 2 has nothing!");
}
}
}
Finally, below is the Main Method:
When I run this code, MyVariable returns null, I am assuming I am accessing the variable before it is assigned it's values?
How do I get the variable with the values assigned in the Method class?
namespace Classes
{
class Program
{
static void Main(string[] args)
{
MyMethods myMethod = new MyMethods();
MyVariableClass myVarClass = new MyVariableClass();
string something = "something";
string nothingHere = null;
myMethod.DoSomeStuff(something, nothingHere);
//I need to call MyVariable here
//Or be able to access it's values assigned in the MyMethod Class.
Console.Write(myVarClass.MyVariable);
Console.ReadKey();
}
}
}
Problem : You are working on two different objects.
you are creating an object with an instance variable myVarClass in MyMethods class.
you are creating one more new object with an instance variable myVarClass in Main() method.
Note : You should always remeber that in object oriented programming objects are independent and maintain their own copy so modifying one object parameters/properties doesnot effect the other object parameters or properties.
Solution : instead of creating two different object create only one object with instance variable myVarClass in Main() method and pass it to the myClass method.
so you should change your myClass method DoSomeStuff() as below to accept the instance variable of `MyVariableClass``
public void DoSomeStuff(MyVariableClass myVarClass, string myString1, string myString2)
{
//do something
}
from Main() method call the above method as below:
MyVariableClass myVarClass = new MyVariableClass();
string something = "something";
string nothingHere = null;
myMethod.DoSomeStuff(myVarClass, something, nothingHere);
Complete Code:
namespace Classes
{
class MyMethods
{
public void DoSomeStuff(MyVariableClass myVarClass, string myString1, string myString2)
{
myVarClass.MyVariable = (!string.IsNullOrEmpty(myString2)
? myString2 : "String 2 has nothing!");
}
}
}
and Main Program should be :
namespace Classes
{
class Program
{
static void Main(string[] args)
{
MyMethods myMethod = new MyMethods();
MyVariableClass myVarClass = new MyVariableClass();
string something = "something";
string nothingHere = null;
myMethod.DoSomeStuff(myVarClass, something, nothingHere);
//I need to call MyVariable here
//Or be able to access it's values assigned in the MyMethod Class.
Console.Write(myVarClass.MyVariable);
Console.ReadKey();
}
}
}
The myVarClass member of MyMethods is private by default, so if you want to be able to call it from outside the class itself, then you need to make it public.
Once public, you'll able to do:
static void Main(string[] args)
{
MyMethods myMethod = new MyMethods();
MyVariableClass myVarClass = new MyVariableClass();
string something = "something";
string nothingHere = null;
myMethod.DoSomeStuff(something, nothingHere);
//I need to call MyVariable here
//Or be able to access it's values assigned in the MyMethod Class.
Console.Write(myMethod.myVarClass.MyVariable);
Console.ReadKey();
}
Also, be careful with the fact that the myVarClass defined in main is a completely different object.
Cheers
Define you class as:
namespace Classes
{
class MyMethods
{
public MyVariableClass MyVarClass {get; private set;}
public void DoSomeStuff(string myString1, string myString2)
{
if(MyVarClass == null)
{
MyVarClass = new MyVariableClass();
}
MyVarClass.MyVariable = (!string.IsNullOrEmpty(myString2)
? myString2 : "String 2 has nothing!");
}
}
}
then use as:
namespace Classes
{
class Program
{
static void Main(string[] args)
{
MyMethods myMethod = new MyMethods();
string something = "something";
string nothingHere = null;
myMethod.DoSomeStuff(something, nothingHere);
//I need to call MyVariable here
//Or be able to access it's values assigned in the MyMethod Class.
Console.Write(myMethod.MyVarClass.MyVariable);
Console.ReadKey();
}
}
}

Passing a List to another class

I know some codes here are not clear. I'm still in the process of trying out things. I've got three questions, why does an error shows up when adding a string in my list? How do I pass the List in Class1 to my main class? And is my syntax correct in List passArr? Not sure if I should add parenthesis at the end of passArr.
class Class1
{
public static List<string> passArr
{
get;
set;
}
public static void passIt()
{
passArr.Add("A"); //Error: Object reference not set to an instance of an object
}
}
Main Class
class Program
{
static void Main(string[] args)
{
Class1.passIt();
List<string> passArr1 = Class1.passArr;
foreach (string s in passArr1)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
}
You're never creating a list, so the passArr property (which needs renaming, by the way) always has a value of null. You need something like:
Class1.passArr = new List<string>();
at some point. Another alternative would be to make it a read-only property backed by a field with an initializer:
private static readonly List<string> passArr = new List<string>();
public static List<string> PassArr { get { return passArr; } }
(This complies with naming convention in terms of case, but it's still not a meaningful name, of course.)
Thanks to Jon Skeet and Sayse for the answers. It's all now clear to me, the real problem is I'm trying to add something in the list (using passIt method) without creating a new object for the list.
Here's my new code:
Main Class
class Program
{
static void Main(string[] args)
{
Class1 cs = new Class1();
cs.passIt();
foreach (string s in cs.passArr)
{
Console.WriteLine("Inside main: " + s);
}
Console.ReadLine();
}
}
Class1
class Class1
{
public List<string> passArr
{
get;
set;
}
public void passIt()
{
passArr = new List<string>();
passArr.Add("A");
}
}

Categories