I'm beating my head against the wall pretty severely with this. I have several variables inside a C# console application that I would like to re-use. However, I cannot for the life of me re-use the variables in another class. I would love any help or pointers you could provide - I've searched for quite some time and I'm completely stumped.
EDIT: Yes, the variables are inside my Main function. Sorry for leaving this out.
EDIT: Heavily redacted code below. The variable values I'd like to re-use in another class are in the middle. There are more but those 3 should be sufficient for the sample. Thanks for the assistance!!!
public static class MyApp
{
static void Main(string[] args)
{
// loads XML doc
foreach (XmlNode node in nodes)
{
try
{
// does a bunch of stuff
// Parses variables from REST API
XDocument docdetailxml = XDocument.Parse(xmldoc);
XNamespace ns = docdetailxml.Root.GetDefaultNamespace();
var buid = docdetailxml.Root.Element(ns + "busid").Value;
var bname = docdetailxml.Root.Element(ns + "busname").Value;
var bcount = docdetailxml.Root.Element(ns + "buscount").Value;
// Invoke SQL connection string
// Trigger Stored Procedure and write values to database
// If needed, trigger email notification
// Close connections
}
catch (Exception e)
{
Console.WriteLine("Error encountered: " + e.Message);
// Exit the application
System.Environment.Exit(1);
}
finally
{
// Exit the application
// System.Environment.Exit(0);
}
}
}
private static void GetConnectionString()
{
throw new NotImplementedException();
}
private static void GetConnectionStrings()
{
throw new NotImplementedException();
}
}
}
you should define public property or public field
public class Student
{
public string Name {get;set;}
}
and when you want to pass value you can assign this value to property
Student st = new Student();
st.Name = "your value";
or you can use class constructor too.
If the variable denote some information about an object (like name, id, etc.) then they should be encapsulated in a class. The instance of the class (called an object) should be used to access this information.
As you already have the variables that represent an object, the next step would be to group these variables into classes. These variables are represented as properties in the class. The operations performed on these members should be available as methods. Furthermore the access modifiers decide the visibility of the members.
Going through your example, I can identify 3 variables that represent a Customer (assumption, I am not sure of the exact use case). These will form the Customer class.
class Customer
{
// You can either pass the UID through the constructor or
// expose a public setter to allow modification of the property
public Customer(string uid)
{
this.UID = uid;
}
public string UID { get; private set; }
public string Name { get; set; }
public string Count { get; set; }
}
Furthermore, the foreach loop can be split into 2 parts for resuablity
Read from the xml nodes and create a list of customers
Perform the database operations (like trigger stored procedures, write values, etc.) on the list of customers
Additionally, you can create another class that does the operations (business logic) that you are performing in the console application. This will allow you to reuse the same logic in case you move it to another application (like winforms or web service).
More information
Object oriented programming
Object oriented concepts in C#
Principles Of Object Oriented Design
I think there's a dedicated forum for struts on this site, best look there for more info.
Quick answer: the primary way of passing values from one action to another (I think you are working with struts Action classes?) is to put the values into the request or session (so, first job for you would be to read up on those topics: HttpServletRequest and HttpSession). Struts action classes do their work in the execute() method, and that method has a parameter of type HttpServletRequest. From the request you can get a handle to the session.
And both request and session offer methods getAttribute() and setAttribute(). So, to pass data from one action to another, set that data as a (request or session) attribute, then read out the attribute in the next action again.
The Program class is probably Static so you'll have to access those fields by class name instead of instance.
class Program
{
public string Name = "a name";
static void Main(string[] args)
{
Name = "Hello"; //You can't do this, compile error
Program p = new Program();
p.Name = "Hi"; //You can do this
SecondName = "Sn"; //You can do this
Program.SecondName = "Tr"; //You can do this too
}
public static string SecondName = "Peat";
}
Related
I have a class like this and the purpose is to set these Boolean values in the data layer with purpose of persisting these values in through out application's life cycle.
public class ProjectFeatureIndicatorMetadata
{
public bool? SprcCustomIncludesInd;
public bool? SprcCustomVariablesInd;
public bool? SprcRatingFlowInd;
public bool? SprcFactorSetsGenerationInd;
public static void SetFeatureIndicatorValues(string name, bool value)
{
ProjectFeatureIndicatorMetadata indicators = new Data.ProjectFeatureIndicatorMetadata();
if(name == "SprcCustomIncludesInd") { indicators.SprcCustomIncludesInd = value; }
if(name == "SprcCustomVariablesInd") { indicators.SprcCustomVariablesInd = value; }
if(name == "SprcRatingFlowInd") { indicators.SprcRatingFlowInd = value; }
if(name == "SprcFactorSetsGenerationInd") { indicators.SprcFactorSetsGenerationInd = value; }
}
}
Then I have the data layer, pretty straight forward. I can confirm that database call is made and values are being fetched and at this level, the indicators are assigned values:
public void GetCachedProjectFeatureIndicatorsStatus(ProjectIdentifier projectId)
{
ProjectFeatureIndicatorMetadata indicatorData = new ProjectFeatureIndicatorMetadata();
GetSpHelper().ExecuteReader(
spName: "ITV.usp_ProjectFeatureIndicators_GetByProjectId",
parmsDg: parms => parms.AddWithValue("#ProjectId", projectId.Guid),
methodDg: reader =>
{
while (reader.Read())
{
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomVariablesInd", reader.Column<bool>("SprcCustomVariablesInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcRatingFlowInd", reader.Column<bool>("SprcRatingFlowInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcFactorSetsGenerationInd", reader.Column<bool>("SprcFactorSetsGenerationInd"));
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomIncludesInd", reader.Column<bool>("SprcCustomIncludesInd"));
}
return true;
});
}
The application start up class calls middle layer through an interface. Below is hot it's implemented. The four 'vars' are just a test code but the bottom line is, values for the indicator variables are null. And I don't know why.
Data.GetCachedProjectFeatureIndicatorStatus(project);
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
var sprcCustomIncludesInd = indicators.SprcCustomIncludesInd;
var sprcCustomVariablesInd = indicators.SprcCustomVariablesInd;
var sprcFactorSetsGenerationInd = indicators.SprcFactorSetsGenerationInd;
var sprcRatingFlowInd = indicators.SprcRatingFlowInd;
The Data object is class variable in the start up class:
private ProjectData Data
{
[Pure, DebuggerStepThrough]
get { return ProjectDataProvider.ProjectData; }
}
ProjectData is large class that holds lot of other stuff but my code only has this call to the interface:
public void GetCachedProjectFeatureIndicatorStatus(ProjectIdentifier projectId)
{
_server.GetCachedProjectFeatureIndicatorStatus(projectId);
}
Then another class that has the following method that is the main logic for this task:
public void GetCachedProjectFeatureIndicatorStatus(ProjectIdentifier projectId)
{
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
using (new WriteLock(_lock))
{
if (indicators.SprcCustomIncludesInd != null ||
indicators.SprcCustomVariablesInd != null ||
indicators.SprcFactorSetsGenerationInd != null ||
indicators.SprcRatingFlowInd != null)
{
return;
}
else
{
GetProjectFeatureIndicatorsStatus(projectId);
return;
}
}
}
public virtual void GetProjectFeatureIndicatorsStatus(Guid projectId)
{
string PROJECT_SERVER_SQL_CONNECTION_STRING = ConfigurationManager.ConnectionStrings["ConfigConnectionString"].ConnectionString;
var configConnectionFactory = new ManualConnectionFactory(PROJECT_SERVER_SQL_CONNECTION_STRING);
var projectFeatureIndicatorTable = new ProjectFeatureIndicatorsTable(configConnectionFactory);
projectFeatureIndicatorTable.GetCachedProjectFeatureIndicatorsStatus(projectId);
}
I don't fully understand some of your code, like why in your method that has a DataReader, you make a new object instance of ProjectFeatureIndicatorMetaData but then you start looping the reader and make a bunch of static calls like:
while (reader.Read())
{
ProjectFeatureIndicatorMetadata.SetFeatureIndicatorValues(
"SprcCustomVariablesInd", reader.Column<bool>("SprcCustomVariablesInd"));
This won't do anything with the instance you just made, and you don't appear to access the static again outside the data reading loop, nor do you return the instance you made - you instead make another new instance in a different method and then try to access its properties (which will be null)
ProjectFeatureIndicatorMetadata indicators = new ProjectFeatureIndicatorMetadata();
using (new WriteLock(_lock))
{
if (indicators.SprcCustomIncludesInd != null ||
Ultimately if you want your data to travel round your app you have to make an instance, fill it with data and then pass it somewhere (call a method and pass it as a parameter/return it from a method to a method that captures the return value). Right now you have some static things, some non static things and whenever you want to do anything you make a new instance, fill it with data and then immediately throw it away, or you make a new instance and try to read from it as though you expect it to contain data. It's like you expect statics to be some sort of defaulting mechanism that, once called, mean that every new instance you make of that type gets the "defaults" that were set by calling the static methods - statics aren't like that. Statics are more like "there is one instance of the static stuff, that the runtime makes for you, but to access it you must always use it in a static way(no instance variables, just the type name)" - you're mixing "new" (==make a new instance) with static(==a single already existing instance the runtime made)
I'd generally advise to stay away from statics as a way of passing data around; as global variables they're almost always a bad idea in potentially concurrent situations. If you're setting up a cache of commonly used data at startup they may make sense but it introduces a high level of coupling to your classes; every class becomes dependent on the static and has to know what it is and cannot function without it. If you code in a more Dependency Injection style where you give every class instance the data it needs to function when you construct it, you don't get to a place where all classes depend on one - instead they use the data they're given and it isn't mandated how it gets it - you can use that class in a future project just by dropping it in and providing the same initial data from a different way
My question is: Can I define a static method "meth1" in a static class "classB" that, when called from "classA", searches for a specific field (in "classA", not in the class in which is defined)?
I try to explain better: I need to do something like this:
public class classA
{
string someText;
int anInt;
bool trueOrFalse;
public classA()
{
...
...
var variable = classB.meth1("variableName");
...
...
}
}
public static classB
{
public static object meth1(string name)
{
...
... //use "name" to find the variable with that name in the class from which "meth1" is called.
...
}
}
That because I have to read a backup of "last run values" of variables contained in a .txt file, written line by line as "variable name = value".
So I read the .txt, create an hashtable "backupHashtable" which contains ("variable name";"value"), and then I want to search variables by string "variable name" and reset them to "value".
If someone of you knows a better procedure I'm listening. Maybe the use of a Dictionary?
Thank you!
UPDATING
Ok, now I have a clearer idea of what I want to do: I want to implement a class "ClassB", separate from my main class "classA". In this new class I would have a "meth1" method which, running in a separate thread, saves every 10 seconds (for example) the state of some variables belonging to "classA". To communicate the "meth1" what are the variables that he has to save, I want to use a list containing the names (in the format "string", that's what I thought, but I guess it's not the only way) of these variables.
If you're wondering why I want to do this in a separate thread the answer is this: my application performs some recognition operation of some objects in live stream images from multiple cameras and then ancillary operations must be isolated as much as possible from the main code to increase the speed of execution.
Now, perhaps, it is more understandable what I said before.
Yes, but you also need to pass a reference to the instance of A. Then use reflection to get or set the property.
public static void Meth1(object obj, string propertyName)
{
var prop = obj.GetType().GetProperty(propertyName);
var value = prop.GetValue(obj);
...
}
If I were to get values from a textfile into a class, I think I'd load them in a dictionary first, and then set all properties one by one. (Maybe unless there are, say, hundreds of properties). When using reflection, there is a chance that the textfile contains the name of a property you don't want to be changed from outside.
object value;
if (dict.TryGetValue("someProperty", out value)) { a.SomeProperty = value; }
I have a WinForms app written in C# which has a lot of custom Classes.
Many of those Clases share similar Properties and Methods, and I have been able to cut down on the Coding by using Inheritance.
However, my Classes also have a lot of similar Static Methods (often the only thing that differs from one implementation to another between Classes is the reference to the Class itself. A very dumbed down example of this might be -
public class MyClass1()
{
public string IdentifyYourself()
{
return "This is the IdentifyYourself method in " + typeof(MyClass1).Name;
}
}
public class MyClass2()
{
public string IdentifyYourself()
{
return "This is the IdentifyYourself method in " + typeof(MyClass2).Name;
}
}
Is there a way to generalize the code in the IdentifyYourself() method so that there is no need to keep restating the Class in each implementation?
If these were not Static Methods then I could do something like
this.GetType().Name;
But of course the 'this' keyword is unavailable in a Static Method.
You may be wondering why these need to be Static methods. However the above example is not my actual code but a simplified version of the issue I am having. An actual example from my code (but still one of the shorter examples) is as follows -
public static DataTable List(bool active = true)
{
try
{
string table = typeof(MyClass).Name;
string sqlText = "SELECT * FROM [" + table + "] WHERE Active = #Active;";
SqlCommand sqlCom = new SqlCommand(sqlText);
sqlCom.Parameters.AddWithValue("#Active", active);
DataTable results = Express.GetTable(sqlCom);
return results;
}
catch (Exception eX)
{
...
}
}
The Code for the List() implementation differs from one Class to the next only in the first line
string table = typeof(MyClass).Name;
I'm thinking that if I could generalize this in some way, I could re-factor the code as follows -
public static DataTable List(bool active = true)
{
try
{
string nameOfClass = //...some generalized way of obtained the Name of the class...//
return UtilityClass.List(nameOfClass);
}
...
}
It is then a straight copy and paste of just a couple of lines of code each time I want to implement this in a new class and all the more detailed code can be placed in a Utility Class. The advantage of this isn't just avoiding having to type the name of each Class in each implementation, but also, if the details of the SQL operations need to change, it only has to be changed in one place.
The classic way to do that would be generics:
public static DataTable List<T>(bool active = true)
{
try
{
string table = typeof(T).Name;
// ...
} ....
and
var table = YourStaticClass.List<MyClass1>();
Frankly, however, I would also recommend making it return List<T> rather than DataTable. That depends a bit on what Express is, however (but: "dapper" would be trivial to use to do the query into a List<T>)
I am trying to design a factory class that will make it easy for people on my team to add new "actions", I want the properties of the class to be immutable but for debugging purposes I the delegates need to be able to reference properties on the containing class.
Consider the following class:
public class NamedAction
{
public NamedAction(string name, Action action)
{
// Here there is some additional validation,
// such as null parameter checking, etc.
Name = name;
Action = action;
}
public string Name { get; private set; }
public Action Action { get; private set; }
public override string ToString()
{
return "Action: " + Name;
}
}
In a factory class I have the following method to create an instance of a special named action:
private static NamedAction GetSpecialAction()
{
NamedAction na = null;
na = new NamedAction(
"SpecialAction",
() => {
Console.WriteLine("My name is " + na.Name + " and I am special");
Console.WriteLine("Hi, its " + na.Name + " again. I like kittens.");
}
);
return na;
}
The problem I have with this is that ReSharper is telling that the second Console.WriteLine is accessing a modified closure. I guess its because the captured variable is actually still "null" when its reference is captured in the construction of the delegate because it is a parameter to the constructor.
To enforce correct usage I want to guarantee that the Action is not null and is immutable, and so far I haven't found any way to do it without a constructor. I thought about using a builder pattern but I don't see how you could provide access to "self" (this) in side the assigned actions, I'm wary about telling my team to ignore the modified closure warning.
I have an idea where I people could create blueprint/objects which are then sent to a builder/assembler class returning a concrete object but that really doesn't solve my problem of guaranteeing non-null at compile time.
Before giving up I was hoping there was some elegant solution to my problem...
I've created a very simple helper class that I can use in my ASP.Net pages. The idea is that it is supposed to be a very simple way to log an on-page error or success (not a form validation error) and then display it to the user.
In my public helper class I have a class which has certain properties, as shown below:
public class UserMessage
{
public UserMessage()
{
Messages = new Dictionary<string, string>();
}
public string SummaryMessage;
public Dictionary<string, string> Messages;
public bool ShowMessages;
public bool ShowAsError;
}
I then have a variable which is used to store an instance of the UserMessage class, like so:
private static UserMessage _userMessage { get; set; }
I then have two public static methods, one to log a message, the other to display all the messages, like so:
public static void LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError)
{
_userMessage = new UserMessage();
_userMessage.SummaryMessage = summaryMessage;
_userMessage.ShowMessages = showIndividualMessages;
_userMessage.ShowAsError = showAsError;
}
public static string DisplayUserMessages()
{
if (_userMessage == null)
return string.Empty;
StringBuilder messageString = new StringBuilder();
messageString.AppendFormat("\n");
messageString.AppendLine(string.Format("<div class=\"messageSummary {0}\">", (_userMessage.ShowAsError) ? "invalid" : "valid"));
messageString.AppendLine(string.Format("<h3>{0}</h3>", _userMessage.SummaryMessage));
messageString.AppendLine("</div>");
return messageString.ToString();
}
The problem I have is that the _userMessage variable has to be a static variable, otherwise I get the error message "An object reference is required for the non-static field.......". The problem with the variable being static is that is stays in memory, so if the user receives an error message and then visits another page - the error message is still displayed!
I'm sure this is because I missed OOP 101, but how should I correct this?
Do not use static variable to keep messages per user! ASP.NET application is multi-threaded and using static variable is not thread safe. Store them in Session.
public static void LogSummary(string summaryMessage, ...)
{
HttpContext.Current.Session["userMessages"] = new UserMessage();
...
}
public static string DisplayUserMessages()
{
// get the value from session
var userMessage = (UserMessage)HttpContext.Current.Session["userMessages"];
// do the work
// do the clean up
HttpContext.Current.Session["userMessages"] = null;
// the messages will not be displayed on next request
}
Each request is handled by different thread, so the users will overwrite the _userMessage field and you cannot guarantee that messages for the current user will be displayed.
Pass the reference as an argument to the static member, or have it return a new instance like below:
public static UserMessage LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError)
{
var userMessage = new UserMessage();
userMessage.SummaryMessage = summaryMessage;
userMessage.ShowMessages = showIndividualMessages;
userMessage.ShowAsError = showAsError;
return userMessage;
}
In my opinion you try to face a problem with a wrong approach. Considering that you're developing service side component (ASP.NET) and you have to have perfect isolation between every user visits your site, I personally don't see any reason why do not use a backend database for error message holding where every record can be associated to a single user unique ID.
The simple ACID supported database (in practice almost any on the market) is a perfect fit in this case.
In this way you can pull from the database the message you need at the moment you need, and don't need more worry about any type of memory issue (at least from the perspective of this question)
Hope this helps.
Static variable will be shared within AppDomain - i.e. concurrent requests will share the same instance and hence your approach is problematic.
You should consider putting your user-message instance into the current HttpContext to get per request semantics as needed by your use case. For example,
public class UserMessage
{
public static UserMessage Current
{
get { return HttpContext.Current.Items["_User_Message"] as UserMessage; }
}
public static void LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError)
{
var userMessage = new UserMessage();
userMessage.SummaryMessage = summaryMessage;
...
HttpContext.Current.Items["_User_Message"] = userMessage;
}
public static string DisplayUserMessages()
{
var userMessage = UserMessage.Current;
if (userMessage == null ) return string.Empty;
...
}
// rest of the code
...
}
I would probably also make UserMessage constructor private.