I am using ASP.NET Web Forms and C# in my application. I have a class file named Global.cs, in which I define variables using set and get properties. I use those variables anywhere on any pages by instantiating that class object.
Here is my Global.cs file:
using System;
using System.Data;
using System.Linq;
using System.Web;
/// <summary>
/// Contains my site's global variables.
/// </summary>
public static class Global
{
/// <summary>
/// Global variable storing important stuff.
/// </summary>
public static string gDate;
public static string gMobLength;
public static string gDateFormat;
public static string gApplicationNo;
public static string gBranchNo;
public static string gMemId;
public static string gIsEditable="false";
public static string gLoggedInUserName;
public static string ImportantData
{
get
{
return gDate;
}
set
{
gDate = value;
}
}
public static string MobileLength
{
get
{
return gMobLength;
}
set
{
gMobLength = value;
}
}
public static string DateFormat
{
get
{
return gDateFormat;
}
set
{
gDateFormat = value;
}
}
public static string ApplicationNo
{
get
{
return gApplicationNo;
}
set
{
gApplicationNo = value;
}
}
public static string BranchNo
{
get
{
return gBranchNo;
}
set
{
gBranchNo = value;
}
}
}
Is this a proper way of using variables throughout the project? What are the possible pros and cons with this approach and what approach would you guys take for using global variables?
First, I'd recommend using autoimplemented properties.
public static string BranchNo { get; set; }
Simplifies your code a bit. As to whether or not this is a good approach, it depends. Sometimes simple and straight-forward is better, and this falls into that category. If the values should not change once initialized, you may want to use a proper singleton with initialization:
public class Settings
{
private static Settings _current;
private static readonly object _lock = new object();
public static Settings Current
{
get
{
lock(_lock)
{
if (_current == null) throw new InvalidOperationException("Settings uninitialized");
return _current;
}
}
set
{
if (value == null) throw new ArgumentNullException();
if (_current != null) throw new InvalidOperationException("Current settings can only be set once.");
if (_current == null)
{
lock(_lock)
{
if (_current == null) _current = value;
}
}
}
}
public string ImportantData { get; private set; }
// etc.
}
Initializing settings:
Settings.Current = new Settings{ ImportantData = "blah blah blah"};
Accessing:
var data = Settings.Current.ImportantData;
Outside of the two bromides "globals are bad" and "properties are good" ... there's nothing intrinsically wrong with your approach. Go for it!
IMHO .. PSM
The reason why you do not see the variable after you instantiate that class object is because the variables are declared as static. Static variables are meant to be used by that manor ClassName.variableName or ClassName.PropertyName
Related
I have a public method ValidateWords inside FooService.To test the ValidateWord method, I created IAppSettingWrapper and AppSettingWrapper which returns the Instance of AppSettings.
Inside the test method, I want to substitute NotAllowedWords using NSubstitute. However, it throws an object reference exception. Is there any way for substitution? If it's not possible, how can I refactor my static instance?
public sealed class AppSettings
{
private static object _lockObject = new object();
private static volatile AppSettings? _instance;
private static DateTime _cacheTime;
private Settings[] _settings;
public AppSettings()
{
try
{
_settings = GetSettings();
}
catch { }
}
public static AppSettings Instance
{
get
{
lock (_lockObject)
{
if (_instance == null)
{
_instance = new AppSettings();
}
}
return _instance;
}
}
public List<string> NotAllowedWords
{
get
{
return new List<string>() {
"index",
"change"
};
}
}
public T GetValues<T>(string key,T defaultValue)
{
T result = defaultValue;
var settings = _settings.Where(i => i.Key == key).FirstOrDefault();
result = (T)Convert.ChangeType(settings.Value, typeof(T));
return result;
}
private Settings[]? GetSettings()
{
//gets data from web services
return base.Channel.GetSettings();
}
}
public class Settings
{
public string Key { get; set; }
public string Value { get; set; }
}
public interface IAppSettingsWrapper
{
public AppSettings Instance();
}
public class AppSettingsWrapper : IAppSettingsWrapper
{
public AppSettings Instance()
{
return AppSettings.Instance;
}
}
[TestClass]
public class FooServiceTest{
private IAppSettingsWrapper _appSettingsWrapper;
[TestInitialize]
public void TestInitialize(IAppSettingsWrapper appSettingsWrapper)
{
_appSettingsWrapper = Substitute.For<IAppSettingsWrapper>();
}
private FooService CreateFooService()
{
return new FooService(_appSettingsWrapper);
}
[TestMethod]
public void Throw_Exception_When_Given_Word_Not_Allowed() {
var service = this.CreateFooService();
_appSettingsWrapper.Instance().NotAllowedWords.Returns(new List<string> { "index" });
var word = "index";
Exception ex = Assert.ThrowsException<Exception>(() => service.ValidateWords(word));
Assert.AreEqual("this word is not allowed", ex.Message);
}
}
public class FooService
{
private IAppSettingsWrapper _appSettingsWrapper;
public FooService(IAppSettingsWrapper appSettingsWrapper)
{
_appSettingsWrapper = appSettingsWrapper;
}
public void ValidateWords(string word)
{
if (_appSettingsWrapper.Instance().NotAllowedWords.Contains(word))
{
throw new Exception("this word is not allowed");
}
}
}
The AppSettings.NotAllowedWords property is not substitutable due to it not being virtual and the class being sealed. If you add NSubstitute.Analyzers to your test project it will help you find these cases. (The How NSubstitute Works documentation outlines why this is the case.)
One option is to make AppSettings implement an IAppSettings interface and inject that into FooService (rather than the wrapper). Then you can use a substitute for tests, and AppSettings.Instance for your real code.
I've searched just about everywhere and not even sure it's possible, but what the hey, I thought I would see what you C# wizards might have for a solution or workaround.
TL;DR:
I have a multi-dimensional collection using C# dictionaries and want to indicate what each string in the dictionary is for, something like this:
private Dictionary<string: Area, Dictionary<string: Controller, string: Action>> ActionCollection;
Which of-course does not work. For now I'm just commenting the dictionary.
Suggestions, thoughts, ideas?
You cannot do that, but you could add a summary.
For example:
/// <summary>
/// Dictionary<Area, Dictionary<Controller, Action>>
/// </summary>
private Dictionary<string, Dictionary<string, string>> ActionCollection;
These comments will show up in the intellisense.
Or:
If you want to extract info with reflection, you could use custom attributes
If it is just for readability, you could create aliases for it:
using Area = System.String;
using Controller = System.String;
using Action = System.String;
namespace MyApp
{
public class MyClass
{
private Dictionary<Area, Dictionary<Controller, Action>> ActionCollection;
}
}
But intellisense will show string
#MMM says about invalid xml, you can do this:
/// <summary>
/// Dictionary<Area, Dictionary<Controller, Action>>
/// </summary>
Make a class that pairs the key or the value with the annotation:
class AnnotatedVal {
public string Val {get;}
public string Annotation {get;}
public AnnotatedVal(string val, string annotation) {
// Do null checking
Val = val;
Annotation = annotation;
}
public bool Equals(object obj) {
var other = obj as AnnotatedVal;
return other != null && other.Val == Val && other.Annotation == Annotation;
}
public int GetHashCode() {
return 31*Val.GetHashCode() + Annotation.GetHashCode();
}
}
private Dictionary<AnnotatedVal,Dictionary<AnnotatedVal,AnnotatedVal>> ActionCollection;
Now you can use AnnotatedVal in your dictionaries to assure segregation:
ActionCollection.Add(new AnnotatedVal("hello", "Area"), someDictionary);
if (ActionCollection.ContainsKey(new AnnotatedVal("hello", "Area"))) {
Console.WriteLine("Yes");
} else {
Console.WriteLine("No");
}
if (ActionCollection.ContainsKey(new AnnotatedVal("hello", "Controller"))) {
Console.WriteLine("Yes");
} else {
Console.WriteLine("No");
}
The above should produce
Yes
No
because AnnotatedVal("hello", "Area") and AnnotatedVal("hello", "Controller") use different annotations.
You could wrap each string in it's own class. Then the declaration and intellisense will be descriptive:
public class Area
{
public string area { get; set; }
public override string ToString()
{
return area;
}
}
public class Controller
{
public string controller { get; set; }
public override string ToString()
{
return controller;
}
}
public class Action
{
public string action { get; set; }
public override string ToString()
{
return action;
}
}
private Dictionary<Area, Dictionary<Controller, Action>> ActionCollection;
It's possible by using Tuple Field Names within List:
private List<(string Area, List<(string Controller, string Action)>)> ActionCollection;
That's feature from C# 7.0 or from .NET 4.3 by importing System.ValueTuple nuget.
I'm about to design a class that more often then not will contain a reference to a Null value. It reminded me of nullable Datetime which has a boolean value to indicate if there is an actual value stored.
DateTime? dt = new DateTime?();
if(dt.HasValue)
{
//DoStuff
}
Is it a good coding practice to design a class as follows?
class Computer
{
public string Name;
public string ID;
//...
public bool IsHiveMind;
public HiveMindInfo RegInfo;
}
class HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
...and to use it...
Computer aComputer = GetComputer(...);
if(aComputer.IsHiveMind)
{
Network.DoHostileTakeOver(aComputer); //!
}
How about this code below?
It seems you can remove IsHiveMind variable since HiveMindInfo variable has the same meaning by checking its null or not.
class Computer
{
public string Name;
public string ID;
public HiveMindInfo RegInfo;
}
class HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
Computer aComputer = GetComputer(...);
if (aComputer != null && aComputer.RegInfo != null)
{
Network.DoHostileTakeOver(aComputer);
}
To answer your question, you could implement the code as proposed.
An alternative would be to consider the following design patterns:
Proxy Design Pattern
Strategy Design Pattern
Sample Code
interface ITakeOverStrategy
{
void Execute();
}
class KevinFlynnHackerStrategy : ITakeOverStrategy
{
public void Execute()
{
// a nod to Tron
}
}
class NeoHackerStrategy: ITakeOverStrategy
{
private readonly HiveMindInfo _hiveMindInfo;
public NeoHackerStrategy(HiveMindInfo info)
{
_hiveMindInfo = info;
}
public void Execute()
{
// Mr. Anderson!
}
}
// This is a surrogate class.
// ... The value returned by String.Empty is often used as a surrogate.
class IdleStrategy : ITakeOverStrategy
{
public void Execute()
{
// do nothing
}
}
class Computer
{
private readonly ITakeOverStrategy _takeoverStrategy ;
public Computer(ITakeOverStrategy strategy)
{
_takeoverStrategy = strategy;
}
public Subjugate()
{
// insert epic code here
_takeoverStrategy.Execute();
}
}
Then somewhere in your code you create an instance of Computer with the appropriate strategy:
var info = new HiveMindInfo();
// update instance parameters
var computer = new Computer(new NeoHackerStrategy(info));
computer.Subjugate();
UPDATES
August 13th, 2015 # 10:13 EST
My comment about structs is not within the scope of the original question, and has been removed:
If your classes are only going to contain fields/properties then I would consider converting them into struct.
Just add ? to your object:
class Computer
{
public string Name;
public string ID;
//...
public HiveMindInfo? RegInfo;
}
struct HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
And then check it exactly as you did with datetime:
Computer aComputer = GetComputer(...);
if (aComputer.RegInfo.HasValue)
{
// Do something
}
I need to store list values impermanent and i need to get to that list values in another c# class. the procedure resemble, Session in Asp.net. Anybody please share a few thoughts regarding this idea.
Here is my code:
class1.cs:
ObservableCollection<SampleEntityList> zoneList = new ObservableCollection<SampleEntityList>();
ObservableCollection<SampleEntityList> ztowList = new ObservableCollection<SampleEntityList>();
I need to store this 2 list values some place locally and i need to get to this two list values to another class.. be that as it may, i would prefer not to go as constructor. I need to store this two rundown values locally..
class2.cs:
??
I have endeavored this code:
Made new static class for setting the Property. What's more, I can't get to the property access outside the class..
Here's my code:
static class GlobalTempStorageVariable
{
ObservableCollection<SampleEntityList> zoneListGlobal
= new ObservableCollection<SampleEntityList>();
ObservableCollection<SampleEntityList> ztowListGlobal
= new ObservableCollection<SampleEntityList>();
public static ObservableCollection<SampleEntityList> CurrentListOfInventories
{
get { return zoneListGlobal; }
set { zoneListGlobal = value; }
}
public static ObservableCollection<SampleEntityList> CurrentSelectedInventories
{
get { return ztwoListGlobal; }
set { ztwoListGlobal= value; }
}
}
But this code is not working. Also i am unable to access CurrentListOfInventories & CurrentSelectedInventories outside the class..
class1.cs:
GlobalTempStorageVariable. ???(its not showing the property)..
Any help would be appreciated..
A Static property cannot access non-static field, zoneListGlobal and ztowListGlobal should also be static in order to be accessible by their Properties :
static class GlobalTempStorageVariable
{
static ObservableCollection<SampleEntityList> zoneListGlobal
= new ObservableCollection<SampleEntityList>();
static ObservableCollection<SampleEntityList> ztowListGlobal
= new ObservableCollection<SampleEntityList>();
public static ObservableCollection<SampleEntityList> CurrentListOfInventories
{
get { return zoneListGlobal; }
set { zoneListGlobal = value; }
}
public static ObservableCollection<SampleEntityList> CurrentSelectedInventories
{
get { return ztowListGlobal; }
set { ztowListGlobal = value; }
}
}
You can build your static class with 2 static methods that return your desired object, like this example:
public static class GlobalTempStorageVariable
{
ObservableCollection<SampleEntityList> zoneListGlobal
= new ObservableCollection<SampleEntityList>();
ObservableCollection<SampleEntityList> ztowListGlobal
= new ObservableCollection<SampleEntityList>();
public static ObservableCollection<SampleEntityList> GetCurrentListOfInventories()
{
return zoneListGlobal;
}
public static ObservableCollection<SampleEntityList> GetCurrentSelectedInventories()
{
return ztowListGlobal;
}
}
I have been trying to get the Wolframalpha API for C# working to no avail. I have been trying to use these two resources:
Stack Question
Wolfram API demos
The answer in the post was semi helpful but I can't get anything to compile. I'm new to C# so its a bit overwhelming. I am really having trouble trying to just get it to accept input and then output the result.
If anyone could either help me get this code working so I can work with a valid example or knows of an example project that I can model from it would be appreciated.
This is the code I cut and pasted into a C# (Visual Studio) console project:
namespace WolframAlpha {
using System;
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Net;
using System.IO;
public partial class DefaultPodEntity {
private String _PlainText;
private String _Img;
private String _Title;
private String _ParentTitle;
private Int16 _ParentPosition;
private String _ParentId;
public String PlainText {
get {
return this._PlainText;
}
set {
this._PlainText = value;
}
}
public String Img {
get {
return this._Img;
}
set {
this._Img = value;
}
}
public String Title {
get {
return this._Title;
}
set {
this._Title = value;
}
}
public String ParentTitle {
get {
return this._ParentTitle;
}
set {
this._ParentTitle = value;
}
}
public Int16 ParentPosition {
get {
return this._ParentPosition;
}
set {
this._ParentPosition = value;
}
}
public String ParentId {
get {
return this._ParentId;
}
set {
this._ParentId = value;
}
}
}
public partial class HtmlPodEntity {
private String _Markup;
private String _Title;
private Int16 _Position;
private String _Id;
private String _Css;
private String _Scripts;
public String Markup {
get {
return this._Markup;
}
set {
this._Markup = value;
}
}
public String Title {
get {
return this._Title;
}
set {
this._Title = value;
}
}
public Int16 Position {
get {
return this._Position;
}
set {
this._Position = value;
}
}
public String Id {
get {
return this._Id;
}
set {
this._Id = value;
}
}
public String Css {
get {
return this._Css;
}
set {
this._Css = value;
}
}
public String Scripts {
get {
return this._Scripts;
}
set {
this._Scripts = value;
}
}
}
public partial class PlainTextPodEntity {
private String _PlainText;
private String _Title;
private String _ParentTitle;
private Int16 _ParentPosition;
private String _ParentId;
public String PlainText {
get {
return this._PlainText;
}
set {
this._PlainText = value;
}
}
public String Title {
get {
return this._Title;
}
set {
this._Title = value;
}
}
public String ParentTitle {
get {
return this._ParentTitle;
}
set {
this._ParentTitle = value;
}
}
public Int16 ParentPosition {
get {
return this._ParentPosition;
}
set {
this._ParentPosition = value;
}
}
public String ParentId {
get {
return this._ParentId;
}
set {
this._ParentId = value;
}
}
}
public partial class WolframAlphaFactsContainer : System.Data.Services.Client.DataServiceContext {
public WolframAlphaFactsContainer(Uri serviceRoot) :
base(serviceRoot) {
}
/// <summary>
/// </summary>
/// <param name="Input">Query string Sample Values : weather|msft|derivative of x^4 sin x|SAT scores</param>
/// <param name="Location">Location used for computation Sample Values : Madrid|Springfield, IL</param>
/// <param name="LatitudeLongitude">Latitude/Longitude used for computation Sample Values : 40.42,-3.71|-22.54,-43.12</param>
/// <param name="Width">Width in pixels for images returned Sample Values : 300|500</param>
public DataServiceQuery<DefaultPodEntity> GetImageResults(String Input, String Location, String LatitudeLongitude, Int16? Width) {
if ((Input == null)) {
throw new System.ArgumentNullException("Input", "Input value cannot be null");
}
DataServiceQuery<DefaultPodEntity> query;
query = base.CreateQuery<DefaultPodEntity>("GetImageResults");
if ((Input != null)) {
query = query.AddQueryOption("Input", string.Concat("\'", Input, "\'"));
}
if ((Location != null)) {
query = query.AddQueryOption("Location", string.Concat("\'", Location, "\'"));
}
if ((LatitudeLongitude != null)) {
query = query.AddQueryOption("LatitudeLongitude", string.Concat("\'", LatitudeLongitude, "\'"));
}
if (((Width != null)
&& (Width.HasValue == true))) {
query = query.AddQueryOption("Width", Width.Value);
}
return query;
}
/// <summary>
/// </summary>
/// <param name="Input">Query string Sample Values : weather|msft|derivative of x^4 sin x|SAT scores</param>
/// <param name="Location">Location used for computation Sample Values : Madrid|Springfield, IL</param>
/// <param name="LatitudeLongitude">Latitude/Longitude used for computation Sample Values : 40.42,-3.71|-22.54,-43.12</param>
/// <param name="Width">Width in pixels for images returned Sample Values : 300|500</param>
public DataServiceQuery<HtmlPodEntity> GetHtmlResults(String Input, String Location, String LatitudeLongitude, Int16? Width) {
if ((Input == null)) {
throw new System.ArgumentNullException("Input", "Input value cannot be null");
}
DataServiceQuery<HtmlPodEntity> query;
query = base.CreateQuery<HtmlPodEntity>("GetHtmlResults");
if ((Input != null)) {
query = query.AddQueryOption("Input", string.Concat("\'", Input, "\'"));
}
if ((Location != null)) {
query = query.AddQueryOption("Location", string.Concat("\'", Location, "\'"));
}
if ((LatitudeLongitude != null)) {
query = query.AddQueryOption("LatitudeLongitude", string.Concat("\'", LatitudeLongitude, "\'"));
}
if (((Width != null)
&& (Width.HasValue == true))) {
query = query.AddQueryOption("Width", Width.Value);
}
return query;
}
/// <summary>
/// </summary>
/// <param name="Input">Query string Sample Values : weather|msft|derivative of x^4 sin x|SAT scores</param>
/// <param name="Location">Location used for computation Sample Values : Madrid|Springfield, IL</param>
/// <param name="LatitudeLongitude">Latitude/Longitude used for computation Sample Values : 40.42,-3.71|-22.54,-43.12</param>
/// <param name="Width">Width in pixels for images returned Sample Values : 300|500</param>
public DataServiceQuery<PlainTextPodEntity> GetPlainTextResults(String Input, String Location, String LatitudeLongitude, Int16? Width) {
if ((Input == null)) {
throw new System.ArgumentNullException("Input", "Input value cannot be null");
}
DataServiceQuery<PlainTextPodEntity> query;
query = base.CreateQuery<PlainTextPodEntity>("GetPlainTextResults");
if ((Input != null)) {
query = query.AddQueryOption("Input", string.Concat("\'", Input, "\'"));
}
if ((Location != null)) {
query = query.AddQueryOption("Location", string.Concat("\'", Location, "\'"));
}
if ((LatitudeLongitude != null)) {
query = query.AddQueryOption("LatitudeLongitude", string.Concat("\'", LatitudeLongitude, "\'"));
}
if (((Width != null)
&& (Width.HasValue == true))) {
query = query.AddQueryOption("Width", Width.Value);
}
return query;
}
}
}
This codeplex project claims to cover the latest Wolfram Alpha API and includes a sample:
http://wolframalphaapi20.codeplex.com/
Console applications use a static Main method as their entry point. This routine can normally be found in a file program.cs that is created automatically when a new project for a console application is created.
If the compiler says it can't find Main then it probably was deleted or was never created. Difficult to say without any code to look at. More errors may show when the issue with the Main method was resolved.
I am currently playing with a lib call WolframAlpha.NET. Code source is on github. There is a nuget package (Last published 2019-06-24).
Examples (from readme)
Here is the simplest form of getting data from Wolfram|Alpha:
static void Main(string[] args)
{
//First create the main class:
WolframAlpha wolfram = new WolframAlpha("APPID HERE");
//Then you simply query Wolfram|Alpha like this
//Note that the spelling error will be correct by Wolfram|Alpha
QueryResult results = wolfram.Query("Who is Danald Duck?");
//The QueryResult object contains the parsed XML from Wolfram|Alpha. Lets look at it.
//The results from wolfram is split into "pods". We just print them.
if (results != null)
{
foreach (Pod pod in results.Pods)
{
Console.WriteLine(pod.Title);
if (pod.SubPods != null)
{
foreach (SubPod subPod in pod.SubPods)
{
Console.WriteLine(subPod.Title);
Console.WriteLine(subPod.Plaintext);
}
}
}
}
}
For more examples, take a look at the WolframAlphaNet.Examples and WolframAlphaNet.Tests projects.
You have copy-pasted class definitions (like DefaultPodEntity and WolframAlphaFactsContainer) that allow you to interact with the Wolfram API, but you do not have a definition for the Main() function that defines what your program should be doing with those classes. You will need to add the method definition
static void Main(string[] args)
{
// TODO: call methods of WolframAlphaFactsContainer
}
to one of the classes (e.g. WolframAlphaFactsContainer or a new one, like Program, that is not listed in your question. Once this compiles, you need to replace the TODO comment with C# statements that specify how you are interacting with the WolframAlphaFactsContainer class (e.g. create an instance of that class and call its GetImageResults() method with the proper parameters).
Note: you will need to learn basic C# programming idioms before you can successfully tackle the problem of writing a working, correct program in C# that does what you want to do (as opposed to relying on other people's code).
Note: Read the documentation on Main() and how to pass command line parameters to your program (should you want to do that).
Note: the class WolframAlphaFactsContainer is marked partial, which means there might be other parts of this class (see documentation). If there are, you will need to include those in your code as well.
I know this post is old, but seeing as how it comes up in google near the top:
https://wapiex.codeplex.com/
This is the wrapper I just finished. It includes much more than the other codeplex project. Feel free to use it